Commit 20ec35e3 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge pull request #3463 from ethereum-optimism/develop

Merge develop to master
parents 530e586e 39b7262c
---
'@eth-optimism/contracts-bedrock': patch
---
Add CrossDomainOwnable contracts
---
'@eth-optimism/contracts-bedrock': patch
---
Removes the blockedSystemMessages mapping in favor of a simpler approach to preventing messages from being sent to internal system addresses.
---
'@eth-optimism/sdk': patch
---
Add DAI bridge support to Goerli
---
'@eth-optimism/ci-builder': minor
---
Automate foundry build
---
'@eth-optimism/contracts': patch
---
Quick patch to fix a build issue in the contracts package
---
'@eth-optimism/contracts-bedrock': patch
---
Prevents v0 (legacy) messages from being relayed in the bedrock XDM.
...@@ -175,7 +175,7 @@ jobs: ...@@ -175,7 +175,7 @@ jobs:
fi fi
- run: - run:
name: check go bindings name: check go bindings
command: make && git diff --exit-code -- ':!*_more.go' command: make && git diff --exit-code
working_directory: op-bindings working_directory: op-bindings
js-lint-test: js-lint-test:
......
...@@ -2,7 +2,7 @@ SHELL := /bin/bash ...@@ -2,7 +2,7 @@ SHELL := /bin/bash
pkg := bindings pkg := bindings
all: mkdir bindings more all: version mkdir bindings more
bindings: l1block-bindings \ bindings: l1block-bindings \
l1-cross-domain-messenger-bindings \ l1-cross-domain-messenger-bindings \
...@@ -23,8 +23,12 @@ bindings: l1block-bindings \ ...@@ -23,8 +23,12 @@ bindings: l1block-bindings \
weth9-bindings \ weth9-bindings \
deployer-whitelist-bindings deployer-whitelist-bindings
version:
forge --version
compile: compile:
cd ../packages/contracts-bedrock/ && \ cd ../packages/contracts-bedrock/ && \
yarn clean && \
npx hardhat compile npx hardhat compile
l1-cross-domain-messenger-bindings: compile l1-cross-domain-messenger-bindings: compile
...@@ -88,7 +92,7 @@ more: ...@@ -88,7 +92,7 @@ more:
go run ./gen/main.go \ go run ./gen/main.go \
-artifacts ../packages/contracts-bedrock/artifacts \ -artifacts ../packages/contracts-bedrock/artifacts \
-out ./bindings \ -out ./bindings \
-contracts OptimismMintableERC20Factory,L2StandardBridge,L1BlockNumber,DeployerWhitelist,Proxy,OptimismPortal,L2ToL1MessagePasser,L2CrossDomainMessenger,GasPriceOracle,SequencerFeeVault,L1Block,LegacyERC20ETH,WETH9,GovernanceToken \ -contracts OptimismMintableERC20Factory,L2StandardBridge,L1BlockNumber,DeployerWhitelist,Proxy,OptimismPortal,L2ToL1MessagePasser,L2CrossDomainMessenger,GasPriceOracle,SequencerFeeVault,L1Block,LegacyERC20ETH,WETH9,GovernanceToken,L1CrossDomainMessenger \
-package bindings -package bindings
mkdir: mkdir:
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":2672,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":2677,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}" const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":2850,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":2855,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}"
var DeployerWhitelistStorageLayout = new(solc.StorageLayout) var DeployerWhitelistStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":50016,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1649,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer0\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1652,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer1\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1655,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1658,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1661,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":27557,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1727,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer0\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1730,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer1\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1733,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1736,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1739,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var GasPriceOracleStorageLayout = new(solc.StorageLayout) var GasPriceOracleStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":1895,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"number\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":1898,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"timestamp\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":1901,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"basefee\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1904,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"hash\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_bytes32\"},{\"astId\":1907,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"sequenceNumber\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint64\"}],\"types\":{\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"}}}" const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":2074,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"number\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2077,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"timestamp\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_uint64\"},{\"astId\":2080,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"basefee\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":2083,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"hash\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_bytes32\"},{\"astId\":2086,\"contract\":\"contracts/L2/L1Block.sol:L1Block\",\"label\":\"sequenceNumber\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint64\"}],\"types\":{\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"}}}"
var L1BlockStorageLayout = new(solc.StorageLayout) var L1BlockStorageLayout = new(solc.StorageLayout)
......
This diff is collapsed.
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":25117,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer0\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint256\"},{\"astId\":25120,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer1\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":25127,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":26024,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer0\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint256\"},{\"astId\":26027,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer1\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":26034,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var L2StandardBridgeStorageLayout = new(solc.StorageLayout) var L2StandardBridgeStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":2365,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":2368,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"nonce\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":2543,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":2546,\"contract\":\"contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser\",\"label\":\"nonce\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var L2ToL1MessagePasserStorageLayout = new(solc.StorageLayout) var L2ToL1MessagePasserStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":50137,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":50143,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":50145,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":50147,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":50149,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":24038,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":24041,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":27756,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":27762,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":27764,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":27766,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":27768,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":24945,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":24948,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var LegacyERC20ETHStorageLayout = new(solc.StorageLayout) var LegacyERC20ETHStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":26027,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":26030,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1374,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1344_storage\"},{\"astId\":1379,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":947,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":960,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":965,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"53\",\"type\":\"t_array(t_uint256)48_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1344_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":26934,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":26937,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1377,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1347_storage\"},{\"astId\":1382,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":950,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":963,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":968,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"53\",\"type\":\"t_array(t_uint256)48_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1347_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var OptimismPortalStorageLayout = new(solc.StorageLayout) var OptimismPortalStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":2513,\"contract\":\"contracts/L2/SequencerFeeVault.sol:SequencerFeeVault\",\"label\":\"l1FeeWallet\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"}}}" const SequencerFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":2691,\"contract\":\"contracts/L2/SequencerFeeVault.sol:SequencerFeeVault\",\"label\":\"l1FeeWallet\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"}}}"
var SequencerFeeVaultStorageLayout = new(solc.StorageLayout) var SequencerFeeVaultStorageLayout = new(solc.StorageLayout)
......
...@@ -112,14 +112,10 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block, proxyL1Stand ...@@ -112,14 +112,10 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block, proxyL1Stand
return immutable, nil return immutable, nil
} }
// StorageConfig represents the storage configuration for the L2 predeploy
// contracts.
type StorageConfig map[string]state.StorageValues
// NewL2StorageConfig will create a StorageConfig given an instance of a // NewL2StorageConfig will create a StorageConfig given an instance of a
// Hardhat and a DeployConfig. // Hardhat and a DeployConfig.
func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1StandardBridge common.Address, proxyL1CrossDomainMessenger common.Address) (StorageConfig, error) { func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1StandardBridge common.Address, proxyL1CrossDomainMessenger common.Address) (state.StorageConfig, error) {
storage := make(StorageConfig) storage := make(state.StorageConfig)
storage["L2ToL1MessagePasser"] = state.StorageValues{ storage["L2ToL1MessagePasser"] = state.StorageValues{
"nonce": 0, "nonce": 0,
...@@ -134,10 +130,6 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1Standar ...@@ -134,10 +130,6 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block, proxyL1Standar
"xDomainMsgSender": "0x000000000000000000000000000000000000dEaD", "xDomainMsgSender": "0x000000000000000000000000000000000000dEaD",
"msgNonce": 0, "msgNonce": 0,
"otherMessenger": proxyL1CrossDomainMessenger, "otherMessenger": proxyL1CrossDomainMessenger,
"blockedSystemAddresses": map[any]any{
predeploys.L2CrossDomainMessenger: true,
predeploys.L2ToL1MessagePasser: true,
},
} }
storage["GasPriceOracle"] = state.StorageValues{ storage["GasPriceOracle"] = state.StorageValues{
"_owner": config.GasPriceOracleOwner, "_owner": config.GasPriceOracleOwner,
......
...@@ -32,7 +32,7 @@ var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d ...@@ -32,7 +32,7 @@ var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d
func TestBuildL2DeveloperGenesis(t *testing.T) { func TestBuildL2DeveloperGenesis(t *testing.T) {
hh, err := hardhat.New( hh, err := hardhat.New(
"goerli", "alpha-1",
nil, nil,
[]string{"../../packages/contracts-bedrock/deployments"}, []string{"../../packages/contracts-bedrock/deployments"},
) )
......
...@@ -62,7 +62,7 @@ func setProxies(db vm.StateDB, proxyAdminAddr common.Address, namespace *big.Int ...@@ -62,7 +62,7 @@ func setProxies(db vm.StateDB, proxyAdminAddr common.Address, namespace *big.Int
// SetImplementations will set the implmentations of the contracts in the state // SetImplementations will set the implmentations of the contracts in the state
// and configure the proxies to point to the implementations. It also sets // and configure the proxies to point to the implementations. It also sets
// the appropriate storage values for each contract at the proxy address. // the appropriate storage values for each contract at the proxy address.
func SetImplementations(db vm.StateDB, storage StorageConfig, immutable immutables.ImmutableConfig) error { func SetImplementations(db vm.StateDB, storage state.StorageConfig, immutable immutables.ImmutableConfig) error {
deployResults, err := immutables.BuildOptimism(immutable) deployResults, err := immutables.BuildOptimism(immutable)
if err != nil { if err != nil {
return err return err
...@@ -102,18 +102,9 @@ func SetImplementations(db vm.StateDB, storage StorageConfig, immutable immutabl ...@@ -102,18 +102,9 @@ func SetImplementations(db vm.StateDB, storage StorageConfig, immutable immutabl
// Set the storage values // Set the storage values
if storageConfig, ok := storage[name]; ok { if storageConfig, ok := storage[name]; ok {
layout, err := bindings.GetStorageLayout(name) if err := state.SetStorage(name, *address, storageConfig, db); err != nil {
if err != nil {
return err return err
} }
slots, err := state.ComputeStorageSlots(layout, storageConfig)
if err != nil {
return fmt.Errorf("%s: %w", name, err)
}
// The storage values must go in the proxy address
for _, slot := range slots {
db.SetState(*address, slot.Key, slot.Value)
}
} }
code := db.GetCode(addr) code := db.GetCode(addr)
......
...@@ -156,6 +156,8 @@ func getElementEncoder(storageType solc.StorageLayoutType, kind string) (Element ...@@ -156,6 +156,8 @@ func getElementEncoder(storageType solc.StorageLayoutType, kind string) (Element
return EncodeAddressValue, nil return EncodeAddressValue, nil
case "t_bool": case "t_bool":
return EncodeBoolValue, nil return EncodeBoolValue, nil
case "t_bytes32":
return EncodeBytes32Value, nil
default: default:
if strings.HasPrefix(target, "t_uint") { if strings.HasPrefix(target, "t_uint") {
return EncodeUintValue, nil return EncodeUintValue, nil
......
...@@ -5,8 +5,15 @@ import ( ...@@ -5,8 +5,15 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)
var (
errInvalidType = errors.New("invalid type")
errUnimplemented = errors.New("type unimplemented")
) )
// StorageValues represents the values to be set in storage. // StorageValues represents the values to be set in storage.
...@@ -14,6 +21,10 @@ import ( ...@@ -14,6 +21,10 @@ import (
// is the value to set in storage. // is the value to set in storage.
type StorageValues map[string]any type StorageValues map[string]any
// StorageConfig represents the storage configuration for the L2 predeploy
// contracts.
type StorageConfig map[string]StorageValues
// EncodedStorage represents the storage key and value serialized // EncodedStorage represents the storage key and value serialized
// to be placed in Ethereum state. // to be placed in Ethereum state.
type EncodedStorage struct { type EncodedStorage struct {
...@@ -34,8 +45,22 @@ func EncodeStorage(entry solc.StorageLayoutEntry, value any, storageType solc.St ...@@ -34,8 +45,22 @@ func EncodeStorage(entry solc.StorageLayoutEntry, value any, storageType solc.St
return encoded, nil return encoded, nil
} }
var errInvalidType = errors.New("invalid type") // SetStorage will set the storage values in a db given a contract name,
var errUnimplemented = errors.New("type unimplemented") // address and the storage values
func SetStorage(name string, address common.Address, values StorageValues, db vm.StateDB) error {
layout, err := bindings.GetStorageLayout(name)
if err != nil {
return err
}
slots, err := ComputeStorageSlots(layout, values)
if err != nil {
return fmt.Errorf("%s: %w", name, err)
}
for _, slot := range slots {
db.SetState(address, slot.Key, slot.Value)
}
return nil
}
// ComputeStorageSlots will compute the storage slots for a given contract. // ComputeStorageSlots will compute the storage slots for a given contract.
func ComputeStorageSlots(layout *solc.StorageLayout, values StorageValues) ([]*EncodedStorage, error) { func ComputeStorageSlots(layout *solc.StorageLayout, values StorageValues) ([]*EncodedStorage, error) {
......
FROM ethereum/client-go:alltools-v1.10.21 as geth FROM debian:bullseye-20220822-slim as foundry-build
WORKDIR /opt
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y curl build-essential git && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \
chmod +x ./rustup.sh && \
./rustup.sh -y
WORKDIR /opt/foundry
FROM ethereumoptimism/foundry:latest as foundry # Only diff from upstream docker image is this clone instead
# of COPY. We select a specific commit to use.
RUN git clone https://github.com/foundry-rs/foundry.git . \
&& git checkout f540aa9ebde88dce720140b332412089c2ee85b6
# Make sure we use bash instead of sh to get the source
# command below
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
RUN source $HOME/.profile && \
cargo build --release && \
strip /opt/foundry/target/release/forge && \
strip /opt/foundry/target/release/cast && \
strip /opt/foundry/target/release/anvil
FROM ethereum/client-go:alltools-v1.10.21 as geth
FROM python:3.8.13-slim-bullseye FROM python:3.8.13-slim-bullseye
ENV GOPATH /go ENV GOPATH=/go
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH
ENV DEBIAN_FRONTEND=noninteractive
COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge COPY --from=foundry-build /opt/foundry/target/release/forge /usr/local/bin/forge
COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast COPY --from=foundry-build /opt/foundry/target/release/cast /usr/local/bin/cast
COPY --from=foundry-build /opt/foundry/target/release/anvil /usr/local/bin/anvil
COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
COPY check-changed.sh /usr/local/bin/check-changed COPY check-changed.sh /usr/local/bin/check-changed
......
...@@ -8,6 +8,13 @@ GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (g ...@@ -8,6 +8,13 @@ GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (g
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68671) GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68671)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74964) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74964)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35777) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35777)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61850)
CrossDomainOwnable_Test:test_onlyOwner() (gas: 34945)
CrossDomainOwnable_Test:test_revertOnlyOwner() (gas: 10619)
CrossDomainOwnable2_Test:test_onlyOwner() (gas: 77782)
CrossDomainOwnable2_Test:test_revertNotSetOnlyOwner() (gas: 8461)
CrossDomainOwnable2_Test:test_revertNotSetOnlyOwner2() (gas: 14598)
CrossDomainOwnable2_Test:test_revertOnlyOwner() (gas: 63704)
DeployerWhitelist_Test:test_owner() (gas: 7591) DeployerWhitelist_Test:test_owner() (gas: 7591)
DeployerWhitelist_Test:test_storageSlots() (gas: 33427) DeployerWhitelist_Test:test_storageSlots() (gas: 33427)
GasPriceOracle_Test:test_baseFee() (gas: 8392) GasPriceOracle_Test:test_baseFee() (gas: 8392)
...@@ -33,21 +40,22 @@ L1BlockTest:test_updateValues() (gas: 28193) ...@@ -33,21 +40,22 @@ L1BlockTest:test_updateValues() (gas: 28193)
L1BlockNumberTest:test_fallback() (gas: 18677) L1BlockNumberTest:test_fallback() (gas: 18677)
L1BlockNumberTest:test_getL1BlockNumber() (gas: 10668) L1BlockNumberTest:test_getL1BlockNumber() (gas: 10668)
L1BlockNumberTest:test_receive() (gas: 25340) L1BlockNumberTest:test_receive() (gas: 25340)
L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24515) L1CrossDomainMessenger_Test:testCannot_L1MessengerPause() (gas: 24537)
L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24562) L1CrossDomainMessenger_Test:testCannot_L1MessengerUnpause() (gas: 24562)
L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24716) L1CrossDomainMessenger_Test:test_L1MessengerMessageVersion() (gas: 24716)
L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 48053) L1CrossDomainMessenger_Test:test_L1MessengerPause() (gas: 48043)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 201405) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 199306)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 194907) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 192914)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 77654) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageSucceeds() (gas: 75685)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 68005) L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageToSystemContract() (gas: 67982)
L1CrossDomainMessenger_Test:test_L1MessengerRelayMessageV0Fails() (gas: 33272)
L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60526) L1CrossDomainMessenger_Test:test_L1MessengerRelayShouldRevertIfPaused() (gas: 60526)
L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38193) L1CrossDomainMessenger_Test:test_L1MessengerReplayMessageWithValue() (gas: 38193)
L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 301590) L1CrossDomainMessenger_Test:test_L1MessengerSendMessage() (gas: 301590)
L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1492584) L1CrossDomainMessenger_Test:test_L1MessengerTwiceSendMessage() (gas: 1492584)
L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 40948) L1CrossDomainMessenger_Test:test_L1MessengerUnpause() (gas: 41003)
L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24305) L1CrossDomainMessenger_Test:test_L1MessengerXDomainSenderReverts() (gas: 24283)
L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 86170) L1CrossDomainMessenger_Test:test_L1MessengerxDomainMessageSenderResets() (gas: 84053)
L1StandardBridge_Test:test_depositERC20() (gas: 574877) L1StandardBridge_Test:test_depositERC20() (gas: 574877)
L1StandardBridge_Test:test_depositERC20To() (gas: 577084) L1StandardBridge_Test:test_depositERC20To() (gas: 577084)
L1StandardBridge_Test:test_depositETH() (gas: 369700) L1StandardBridge_Test:test_depositETH() (gas: 369700)
...@@ -61,18 +69,19 @@ L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40836) ...@@ -61,18 +69,19 @@ L1StandardBridge_Test:test_onlyEOADepositETH() (gas: 40836)
L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 31626) L1StandardBridge_Test:test_onlyL2BridgeFinalizeERC20Withdrawal() (gas: 31626)
L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 31189) L1StandardBridge_Test:test_onlyPortalFinalizeERC20Withdrawal() (gas: 31189)
L1StandardBridge_Test:test_receive() (gas: 516341) L1StandardBridge_Test:test_receive() (gas: 516341)
L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10860) L2CrossDomainMessenger_Test:testCannot_L2MessengerPause() (gas: 10838)
L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 171735) L2CrossDomainMessenger_Test:test_L1MessengerRelayMessageRevertsOnReentrancy() (gas: 169737)
L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8411) L2CrossDomainMessenger_Test:test_L2MessengerMessageVersion() (gas: 8411)
L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31797) L2CrossDomainMessenger_Test:test_L2MessengerPause() (gas: 31809)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 172546) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageFirstStuckSecondSucceeds() (gas: 170452)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 57185) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageSucceeds() (gas: 55211)
L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36217) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageToSystemContract() (gas: 36217)
L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41682) L2CrossDomainMessenger_Test:test_L2MessengerRelayMessageV0Fails() (gas: 18871)
L2CrossDomainMessenger_Test:test_L2MessengerRelayShouldRevertIfPaused() (gas: 41638)
L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122833) L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122833)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 138556) L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 138556)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10598) L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10576)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 54681) L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 52558)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829) L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26829)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25123) L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25123)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91445) L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91445)
......
This diff is collapsed.
...@@ -8,35 +8,35 @@ You can find detailed specifications for the contracts contained within this pac ...@@ -8,35 +8,35 @@ You can find detailed specifications for the contracts contained within this pac
### Contracts deployed to L1 ### Contracts deployed to L1
| Name | Proxy Type | Description | | Name | Proxy Type | Description |
| ---- | ---------- | ----------- | | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| [`L1CrossDomainMessenger`](../../specs/messengers.md) | [`ResolvedDelegateProxy`](./contracts/legacy/ResolvedDelegateProxy.sol) | High-level interface for sending messages to and receiving messages from Optimism | | [`L1CrossDomainMessenger`](../../specs/messengers.md) | [`ResolvedDelegateProxy`](./contracts/legacy/ResolvedDelegateProxy.sol) | High-level interface for sending messages to and receiving messages from Optimism |
| [`L1StandardBridge`](../../specs/bridges.md) | [`L1ChugSplashProxy`](./contracts/legacy/L1ChugSplashProxy.sol) | Standardized system for transfering ERC20 tokens to/from Optimism | | [`L1StandardBridge`](../../specs/bridges.md) | [`L1ChugSplashProxy`](./contracts/legacy/L1ChugSplashProxy.sol) | Standardized system for transfering ERC20 tokens to/from Optimism |
| [`L2OutputOracle`](../../specs/proposals.md#l2-output-oracle-smart-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores commitments to the state of Optimism which can be used by contracts on L1 to access L2 state | | [`L2OutputOracle`](../../specs/proposals.md#l2-output-oracle-smart-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores commitments to the state of Optimism which can be used by contracts on L1 to access L2 state |
| [`OptimismPortal`](../../specs/deposits.md#deposit-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface | | [`OptimismPortal`](../../specs/deposits.md#deposit-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface |
| [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` | | [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` |
| [`ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L1 contracts | | [`ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L1 contracts |
### Contracts deployed to L2 ### Contracts deployed to L2
| Name | Proxy Type | Description | | Name | Proxy Type | Description |
| ---- | ---------- | ----------- | | ---------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| [`GasPriceOracle`](../../specs/predeploys.md#ovm_gaspriceoracle) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L2 gas price configuration values | | [`GasPriceOracle`](../../specs/predeploys.md#ovm_gaspriceoracle) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L2 gas price configuration values |
| [`L1Block`](../../specs/predeploys.md#l1block) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L1 block context information (e.g., latest known L1 block hash) | | [`L1Block`](../../specs/predeploys.md#l1block) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L1 block context information (e.g., latest known L1 block hash) |
| [`L2CrossDomainMessenger`](../../specs/predeploys.md#l2crossdomainmessenger) | [`Proxy`](./contracts/universal/Proxy.sol) | High-level interface for sending messages to and receiving messages from L1 | | [`L2CrossDomainMessenger`](../../specs/predeploys.md#l2crossdomainmessenger) | [`Proxy`](./contracts/universal/Proxy.sol) | High-level interface for sending messages to and receiving messages from L1 |
| [`L2StandardBridge`](../../specs/predeploys.md#l2standardbridge) | [`Proxy`](./contracts/universal/Proxy.sol) | Standardized system for transferring ERC20 tokens to/from L1 | | [`L2StandardBridge`](../../specs/predeploys.md#l2standardbridge) | [`Proxy`](./contracts/universal/Proxy.sol) | Standardized system for transferring ERC20 tokens to/from L1 |
| [`L2ToL1MessagePasser`](../../specs/predeploys.md#ovm_l2tol1messagepasser) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface | | [`L2ToL1MessagePasser`](../../specs/predeploys.md#ovm_l2tol1messagepasser) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface |
| [`SequencerFeeVault`](../../specs/predeploys.md#sequencerfeevault) | [`Proxy`](./contracts/universal/Proxy.sol) | Vault for L2 transaction fees | | [`SequencerFeeVault`](../../specs/predeploys.md#sequencerfeevault) | [`Proxy`](./contracts/universal/Proxy.sol) | Vault for L2 transaction fees |
| [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` | | [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` |
| [`L2ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L2 contracts when sent a transaction from L1 | | [`L2ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L2 contracts when sent a transaction from L1 |
### Legacy and deprecated contracts ### Legacy and deprecated contracts
| Name | Location | Proxy Type | Description | | Name | Location | Proxy Type | Description |
| ---- | -------- | ---------- | ----------- | | --------------------------------------------------------------- | -------- | ------------------------------------------ | ------------------------------------------------------------------------------------- |
| [`AddressManager`](./contracts/legacy/AddressManager.sol) | L1 | - | Legacy upgrade mechanism (unused in Bedrock) | | [`AddressManager`](./contracts/legacy/AddressManager.sol) | L1 | - | Legacy upgrade mechanism (unused in Bedrock) |
| [`DeployerWhitelist`](./contracts/legacy/DeployerWhitelist.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for managing allowed deployers (unused since EVM Equivalence upgrade) | [`DeployerWhitelist`](./contracts/legacy/DeployerWhitelist.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for managing allowed deployers (unused since EVM Equivalence upgrade) |
| [`L1BlockNumber`](./contracts/legacy/L1BlockNumber.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for accessing latest known L1 block number, replaced by `L1Block` | | [`L1BlockNumber`](./contracts/legacy/L1BlockNumber.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for accessing latest known L1 block number, replaced by `L1Block` |
## Installation ## Installation
...@@ -55,9 +55,9 @@ We work on this repository with a combination of [Hardhat](https://hardhat.org) ...@@ -55,9 +55,9 @@ We work on this repository with a combination of [Hardhat](https://hardhat.org)
1. Install Foundry by following [the instructions located here](https://getfoundry.sh/). 1. Install Foundry by following [the instructions located here](https://getfoundry.sh/).
2. Install node modules with yarn (v1) and Node.js (16+): 2. Install node modules with yarn (v1) and Node.js (16+):
```shell ```shell
yarn install yarn install
``` ```
### Build ### Build
......
...@@ -33,18 +33,11 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -33,18 +33,11 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {
* @notice Initializer. * @notice Initializer.
*/ */
function initialize() public initializer { function initialize() public initializer {
address[] memory blockedSystemAddresses = new address[](1); __CrossDomainMessenger_init(Predeploys.L2_CROSS_DOMAIN_MESSENGER);
blockedSystemAddresses[0] = address(this);
__CrossDomainMessenger_init(Predeploys.L2_CROSS_DOMAIN_MESSENGER, blockedSystemAddresses);
} }
/** /**
* @notice Sends a message via the OptimismPortal contract. * @inheritdoc CrossDomainMessenger
*
* @param _to Address of the recipient on L2.
* @param _gasLimit Minimum gas limit that the message can be executed with.
* @param _value ETH value to attach to the message and send to the recipient.
* @param _data Data to attach to the message and call the recipient with.
*/ */
function _sendMessage( function _sendMessage(
address _to, address _to,
...@@ -56,11 +49,16 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -56,11 +49,16 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {
} }
/** /**
* @notice Checks whether the message being sent from the other messenger. * @inheritdoc CrossDomainMessenger
*
* @return True if the message was sent from the messenger, false otherwise.
*/ */
function _isOtherMessenger() internal view override returns (bool) { function _isOtherMessenger() internal view override returns (bool) {
return msg.sender == address(portal) && portal.l2Sender() == otherMessenger; return msg.sender == address(portal) && portal.l2Sender() == otherMessenger;
} }
/**
* @inheritdoc CrossDomainMessenger
*/
function _isUnsafeTarget(address _target) internal view override returns (bool) {
return _target == address(this) || _target == address(portal);
}
} }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
/**
* @title CrossDomainOwnable
* @notice This contract extends the OpenZeppelin `Ownable` contract
* for L2 contracts to be owned by contracts on L1. Note that
* this contract is only safe to be used if the CrossDomainMessenger
* system is bypassed and the caller on L1 is calling the
* OptimismPortal directly.
*/
abstract contract CrossDomainOwnable is Ownable {
/**
* @notice Overrides the implementation of the `onlyOwner` modifier
* to check that the unaliased `msg.sender` is the owner
* of the contract.
*/
function _checkOwner() internal view override {
require(
owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),
"CrossDomainOwnable: caller is not the owner"
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Predeploys } from "../libraries/Predeploys.sol";
import { L2CrossDomainMessenger } from "./L2CrossDomainMessenger.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title CrossDomainOwnable2
* @notice This contract extends the OpenZeppelin `Ownable` contract
* for L2 contracts to be owned by contracts on L1. Note that
* this contract is meant to be used with systems that use the
* CrossDomainMessenger system. It will not work if the OptimismPortal
* is used directly.
*/
abstract contract CrossDomainOwnable2 is Ownable {
/**
* @notice Overrides the implementation of the `onlyOwner` modifier
* to check that the unaliased `xDomainMessageSender`
* is the owner of the contract. This value is set
* to the caller of the L1CrossDomainMessenger.
*/
function _checkOwner() internal view override {
L2CrossDomainMessenger messenger = L2CrossDomainMessenger(
Predeploys.L2_CROSS_DOMAIN_MESSENGER
);
require(
msg.sender == address(messenger),
"CrossDomainOwnable2: caller is not the messenger"
);
require(
owner() == messenger.xDomainMessageSender(),
"CrossDomainOwnable2: caller is not the owner"
);
}
}
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.12; pragma solidity 0.8.15;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
......
...@@ -31,10 +31,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -31,10 +31,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
* @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract. * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.
*/ */
function initialize(address _l1CrossDomainMessenger) public initializer { function initialize(address _l1CrossDomainMessenger) public initializer {
address[] memory blockedSystemAddresses = new address[](2); __CrossDomainMessenger_init(_l1CrossDomainMessenger);
blockedSystemAddresses[0] = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
blockedSystemAddresses[1] = Predeploys.L2_TO_L1_MESSAGE_PASSER;
__CrossDomainMessenger_init(_l1CrossDomainMessenger, blockedSystemAddresses);
} }
/** /**
...@@ -48,12 +45,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -48,12 +45,7 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
} }
/** /**
* @notice Sends a message from L2 to L1. * @inheritdoc CrossDomainMessenger
*
* @param _to Address to send the message to.
* @param _gasLimit Minimum gas limit to execute the message with.
* @param _value ETH value to send with the message.
* @param _data Data to trigger the recipient with.
*/ */
function _sendMessage( function _sendMessage(
address _to, address _to,
...@@ -67,11 +59,16 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver { ...@@ -67,11 +59,16 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
} }
/** /**
* @notice Checks that the message sender is the L1CrossDomainMessenger on L1. * @inheritdoc CrossDomainMessenger
*
* @return True if the message sender is the L1CrossDomainMessenger on L1.
*/ */
function _isOtherMessenger() internal view override returns (bool) { function _isOtherMessenger() internal view override returns (bool) {
return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger; return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == otherMessenger;
} }
/**
* @inheritdoc CrossDomainMessenger
*/
function _isUnsafeTarget(address _target) internal view override returns (bool) {
return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);
}
} }
...@@ -200,6 +200,7 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { ...@@ -200,6 +200,7 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
); );
event RelayedMessage(bytes32 indexed msgHash); event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
event TransactionDeposited( event TransactionDeposited(
address indexed from, address indexed from,
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest, Portal_Initializer } from "./CommonTest.t.sol";
import { CrossDomainOwnable } from "../L2/CrossDomainOwnable.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { Vm } from "forge-std/Vm.sol";
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
contract XDomainSetter is CrossDomainOwnable {
uint256 public value;
function set(uint256 _value) external onlyOwner {
value = _value;
}
}
contract CrossDomainOwnable_Test is CommonTest {
XDomainSetter setter;
function setUp() external {
setter = new XDomainSetter();
}
// Check that the revert message is correct
function test_revertOnlyOwner() external {
vm.expectRevert("CrossDomainOwnable: caller is not the owner");
setter.set(1);
}
// Check that making a call can set the value properly
function test_onlyOwner() external {
assertEq(
setter.value(),
0
);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));
setter.set(1);
assertEq(
setter.value(),
1
);
}
}
contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {
XDomainSetter setter;
function setUp() public override {
super.setUp();
vm.prank(alice);
setter = new XDomainSetter();
}
function test_depositTransaction_crossDomainOwner() external {
vm.recordLogs();
vm.prank(alice);
op.depositTransaction(
address(setter),
0,
10000,
false,
abi.encodeWithSelector(
XDomainSetter.set.selector,
1
)
);
// Simulate the operation of the `op-node` by parsing data
// from logs
Vm.Log[] memory logs = vm.getRecordedLogs();
// Only 1 log emitted
assertEq(logs.length, 1);
Vm.Log memory log = logs[0];
// It is the expected topic
bytes32 topic = log.topics[0];
assertEq(
topic,
keccak256("TransactionDeposited(address,address,uint256,bytes)")
);
// from is indexed and the first argument to the event.
bytes32 _from = log.topics[1];
address from = Bytes32AddressLib.fromLast20Bytes(_from);
assertEq(
AddressAliasHelper.undoL1ToL2Alias(from),
alice
);
// Make a call from the "from" value received from the log.
// In theory the opaque data could be parsed from the log
// and passed to a low level call to "to", but calling set
// directly on the setter is good enough.
vm.prank(from);
setter.set(1);
assertEq(
setter.value(),
1
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
import { CommonTest, Messenger_Initializer } from "./CommonTest.t.sol";
import { CrossDomainOwnable2 } from "../L2/CrossDomainOwnable2.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { Hashing } from "../libraries/Hashing.sol";
import { Encoding } from "../libraries/Encoding.sol";
contract XDomainSetter2 is CrossDomainOwnable2 {
uint256 public value;
function set(uint256 _value) external onlyOwner {
value = _value;
}
}
contract CrossDomainOwnable2_Test is Messenger_Initializer {
XDomainSetter2 setter;
function setUp() override public {
super.setUp();
vm.prank(alice);
setter = new XDomainSetter2();
}
function test_revertNotSetOnlyOwner() external {
vm.expectRevert("CrossDomainOwnable2: caller is not the messenger");
setter.set(1);
}
function test_revertNotSetOnlyOwner2() external {
// set the xdomain messenger storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(setter));
vm.store(address(L2Messenger), key, value);
vm.prank(address(L2Messenger));
vm.expectRevert("CrossDomainOwnable2: caller is not the owner");
setter.set(1);
}
function test_revertOnlyOwner() external {
uint240 nonce = 0;
address sender = bob;
address target = address(setter);
uint256 value = 0;
uint256 minGasLimit = 0;
bytes memory message = abi.encodeWithSelector(
XDomainSetter2.set.selector,
1
);
bytes32 hash = Hashing.hashCrossDomainMessage(
Encoding.encodeVersionedNonce(nonce, 1),
sender,
target,
value,
minGasLimit,
message
);
// It should be a failed message. The revert is caught,
// so we cannot expectRevert here.
vm.expectEmit(true, true, true, true);
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1),
sender,
target,
value,
minGasLimit,
message
);
assertEq(
setter.value(),
0
);
}
function test_onlyOwner() external {
address owner = setter.owner();
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
owner,
address(setter),
0,
0,
abi.encodeWithSelector(
XDomainSetter2.set.selector,
2
)
);
assertEq(
setter.value(),
2
);
}
}
...@@ -133,6 +133,26 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -133,6 +133,26 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
// TODO: might need a test contract // TODO: might need a test contract
// function test_xDomainSenderSetCorrectly() external {} // function test_xDomainSenderSetCorrectly() external {}
function test_L1MessengerRelayMessageV0Fails() external {
address target = address(0xabcd);
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
uint256 senderSlotIndex = 51;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
vm.expectRevert("CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade");
L1Messenger.relayMessage(
0, // nonce
sender,
target,
0, // value
0,
hex"1111"
);
}
// relayMessage: should send a successful call to the target contract // relayMessage: should send a successful call to the target contract
function test_L1MessengerRelayMessageSucceeds() external { function test_L1MessengerRelayMessageSucceeds() external {
address target = address(0xabcd); address target = address(0xabcd);
...@@ -147,12 +167,12 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -147,12 +167,12 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, 0, 0, hex"1111"); bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, hex"1111");
emit RelayedMessage(hash); emit RelayedMessage(hash);
L1Messenger.relayMessage( L1Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
0, // value 0, // value
...@@ -175,11 +195,11 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -175,11 +195,11 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.prank(address(op)); vm.prank(address(op));
vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(0, sender, target, 0, 0, message); L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
vm.store(address(op), 0, bytes32(abi.encode(sender))); vm.store(address(op), 0, bytes32(abi.encode(sender)));
vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(0, sender, target, 0, 0, message); L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
} }
// relayMessage: should revert if eth is sent from a contract other than the standard bridge // relayMessage: should revert if eth is sent from a contract other than the standard bridge
...@@ -191,7 +211,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -191,7 +211,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectRevert( vm.expectRevert(
"CrossDomainMessenger: value must be zero unless message is from a system address" "CrossDomainMessenger: value must be zero unless message is from a system address"
); );
L1Messenger.relayMessage{ value: 100 }(0, sender, target, 0, 0, message); L1Messenger.relayMessage{ value: 100 }(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
} }
// relayMessage: the xDomainMessageSender is reset to the original value // relayMessage: the xDomainMessageSender is reset to the original value
...@@ -205,7 +225,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -205,7 +225,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op)); vm.prank(address(op));
L1Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex"");
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender(); L1Messenger.xDomainMessageSender();
...@@ -229,7 +249,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -229,7 +249,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectCall(target, hex"1111"); vm.expectCall(target, hex"1111");
bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, value, 0, hex"1111"); bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, value, 0, hex"1111");
uint256 senderSlotIndex = 51; uint256 senderSlotIndex = 51;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
...@@ -237,7 +257,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -237,7 +257,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.deal(address(op), value); vm.deal(address(op), value);
vm.prank(address(op)); vm.prank(address(op));
L1Messenger.relayMessage{value: value}( L1Messenger.relayMessage{value: value}(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
value, value,
...@@ -257,7 +277,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -257,7 +277,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.etch(target, address(0).code); vm.etch(target, address(0).code);
vm.prank(address(sender)); vm.prank(address(sender));
L1Messenger.relayMessage( L1Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
value, value,
...@@ -277,7 +297,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -277,7 +297,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
bytes memory message = abi.encodeWithSelector( bytes memory message = abi.encodeWithSelector(
L1Messenger.relayMessage.selector, L1Messenger.relayMessage.selector,
0, Encoding.encodeVersionedNonce(0, 1),
sender, sender,
target, target,
0, 0,
...@@ -285,7 +305,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -285,7 +305,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111" hex"1111"
); );
bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, 0, 0, message); bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
uint256 senderSlotIndex = 51; uint256 senderSlotIndex = 51;
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
...@@ -298,7 +318,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -298,7 +318,7 @@ contract L1CrossDomainMessenger_Test is Messenger_Initializer {
vm.prank(address(op)); vm.prank(address(op));
vm.expectCall(target, message); vm.expectCall(target, message);
L1Messenger.relayMessage( L1Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
0, // value 0, // value
......
...@@ -94,6 +94,24 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -94,6 +94,24 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
L2Messenger.xDomainMessageSender(); L2Messenger.xDomainMessageSender();
} }
function test_L2MessengerRelayMessageV0Fails() external {
address target = address(0xabcd);
address sender = address(L1Messenger);
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
vm.prank(caller);
vm.expectRevert("CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade");
L2Messenger.relayMessage(
0, // nonce
sender,
target,
0, // value
0,
hex"1111"
);
}
function test_L2MessengerRelayMessageSucceeds() external { function test_L2MessengerRelayMessageSucceeds() external {
address target = address(0xabcd); address target = address(0xabcd);
address sender = address(L1Messenger); address sender = address(L1Messenger);
...@@ -106,7 +124,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -106,7 +124,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
bytes32 hash = Hashing.hashCrossDomainMessage( bytes32 hash = Hashing.hashCrossDomainMessage(
0, Encoding.encodeVersionedNonce(0, 1),
sender, sender,
target, target,
0, 0,
...@@ -117,7 +135,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -117,7 +135,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
emit RelayedMessage(hash); emit RelayedMessage(hash);
L2Messenger.relayMessage( L2Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
0, // value 0, // value
...@@ -140,7 +158,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -140,7 +158,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.prank(caller); vm.prank(caller);
vm.expectRevert("CrossDomainMessenger: message cannot be replayed"); vm.expectRevert("CrossDomainMessenger: message cannot be replayed");
L1Messenger.relayMessage(0, sender, target, 0, 0, message); L1Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
} }
// relayMessage: the xDomainMessageSender is reset to the original value // relayMessage: the xDomainMessageSender is reset to the original value
...@@ -150,7 +168,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -150,7 +168,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
vm.prank(caller); vm.prank(caller);
L2Messenger.relayMessage(0, address(0), address(0), 0, 0, hex""); L2Messenger.relayMessage(Encoding.encodeVersionedNonce(0, 1), address(0), address(0), 0, 0, hex"");
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set"); vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L2Messenger.xDomainMessageSender(); L2Messenger.xDomainMessageSender();
...@@ -173,13 +191,13 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -173,13 +191,13 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
uint256 value = 100; uint256 value = 100;
bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, value, 0, hex"1111"); bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, value, 0, hex"1111");
vm.etch(target, address(new Reverter()).code); vm.etch(target, address(new Reverter()).code);
vm.deal(address(caller), value); vm.deal(address(caller), value);
vm.prank(caller); vm.prank(caller);
L2Messenger.relayMessage{value: value}( L2Messenger.relayMessage{value: value}(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
value, value,
...@@ -199,7 +217,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -199,7 +217,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.etch(target, address(0).code); vm.etch(target, address(0).code);
vm.prank(address(sender)); vm.prank(address(sender));
L2Messenger.relayMessage( L2Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
value, value,
...@@ -220,7 +238,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -220,7 +238,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)); address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));
bytes memory message = abi.encodeWithSelector( bytes memory message = abi.encodeWithSelector(
L2Messenger.relayMessage.selector, L2Messenger.relayMessage.selector,
0, Encoding.encodeVersionedNonce(0, 1),
sender, sender,
target, target,
0, 0,
...@@ -228,7 +246,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -228,7 +246,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
hex"1111" hex"1111"
); );
bytes32 hash = Hashing.hashCrossDomainMessage(0, sender, target, 0, 0, message); bytes32 hash = Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, message);
vm.etch(target, address(new CallerCaller()).code); vm.etch(target, address(new CallerCaller()).code);
...@@ -239,7 +257,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer { ...@@ -239,7 +257,7 @@ contract L2CrossDomainMessenger_Test is Messenger_Initializer {
vm.prank(caller); vm.prank(caller);
vm.expectCall(target, message); vm.expectCall(target, message);
L2Messenger.relayMessage( L2Messenger.relayMessage(
0, // nonce Encoding.encodeVersionedNonce(0, 1), // nonce
sender, sender,
target, target,
0, // value 0, // value
......
...@@ -136,15 +136,6 @@ abstract contract CrossDomainMessenger is ...@@ -136,15 +136,6 @@ abstract contract CrossDomainMessenger is
*/ */
mapping(bytes32 => bool) public receivedMessages; mapping(bytes32 => bool) public receivedMessages;
/**
* @notice Mapping of blocked system addresses. Note that this is NOT a mapping of blocked user
* addresses and cannot be used to prevent users from sending or receiving messages.
* This is ONLY used to prevent the execution of messages to specific system addresses
* that could cause security issues, e.g., having the CrossDomainMessenger send
* messages to itself.
*/
mapping(address => bool) public blockedSystemAddresses;
/** /**
* @notice Emitted whenever a message is sent to the other chain. * @notice Emitted whenever a message is sent to the other chain.
* *
...@@ -260,7 +251,17 @@ abstract contract CrossDomainMessenger is ...@@ -260,7 +251,17 @@ abstract contract CrossDomainMessenger is
uint256 _minGasLimit, uint256 _minGasLimit,
bytes calldata _message bytes calldata _message
) external payable nonReentrant whenNotPaused { ) external payable nonReentrant whenNotPaused {
bytes32 versionedHash = Hashing.hashCrossDomainMessage( (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);
// Block any messages that aren't version 1. All version 0 messages have been guaranteed to
// be relayed OR have been migrated to version 1 messages. Version 0 messages do not commit
// to the value or minGasLimit fields, which can create unexpected issues for end-users.
require(
version == 1,
"CrossDomainMessenger: only version 1 messages are supported after the Bedrock upgrade"
);
bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(
_nonce, _nonce,
_sender, _sender,
_target, _target,
...@@ -285,7 +286,7 @@ abstract contract CrossDomainMessenger is ...@@ -285,7 +286,7 @@ abstract contract CrossDomainMessenger is
} }
require( require(
blockedSystemAddresses[_target] == false, _isUnsafeTarget(_target) == false,
"CrossDomainMessenger: cannot send message to blocked system address" "CrossDomainMessenger: cannot send message to blocked system address"
); );
...@@ -365,23 +366,11 @@ abstract contract CrossDomainMessenger is ...@@ -365,23 +366,11 @@ abstract contract CrossDomainMessenger is
* @notice Intializer. * @notice Intializer.
* *
* @param _otherMessenger Address of the CrossDomainMessenger on the paired chain. * @param _otherMessenger Address of the CrossDomainMessenger on the paired chain.
* @param _blockedSystemAddresses List of system addresses that need to be blocked to prevent
* certain security issues. Exact list depends on the network
* where this contract is deployed. See note attached to the
* blockedSystemAddresses variable in this contract for more
* detailed information about what this block list can and
* cannot be used for.
*/ */
// solhint-disable-next-line func-name-mixedcase // solhint-disable-next-line func-name-mixedcase
function __CrossDomainMessenger_init( function __CrossDomainMessenger_init(address _otherMessenger) internal onlyInitializing {
address _otherMessenger,
address[] memory _blockedSystemAddresses
) internal onlyInitializing {
xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;
otherMessenger = _otherMessenger; otherMessenger = _otherMessenger;
for (uint256 i = 0; i < _blockedSystemAddresses.length; i++) {
blockedSystemAddresses[_blockedSystemAddresses[i]] = true;
}
__Context_init_unchained(); __Context_init_unchained();
__Ownable_init_unchained(); __Ownable_init_unchained();
...@@ -393,6 +382,11 @@ abstract contract CrossDomainMessenger is ...@@ -393,6 +382,11 @@ abstract contract CrossDomainMessenger is
* @notice Sends a low-level message to the other messenger. Needs to be implemented by child * @notice Sends a low-level message to the other messenger. Needs to be implemented by child
* contracts because the logic for this depends on the network where the messenger is * contracts because the logic for this depends on the network where the messenger is
* being deployed. * being deployed.
*
* @param _to Recipient of the message on the other chain.
* @param _gasLimit Minimum gas limit the message can be executed with.
* @param _value Amount of ETH to send with the message.
* @param _data Message data.
*/ */
function _sendMessage( function _sendMessage(
address _to, address _to,
...@@ -405,6 +399,21 @@ abstract contract CrossDomainMessenger is ...@@ -405,6 +399,21 @@ abstract contract CrossDomainMessenger is
* @notice Checks whether the message is coming from the other messenger. Implemented by child * @notice Checks whether the message is coming from the other messenger. Implemented by child
* contracts because the logic for this depends on the network where the messenger is * contracts because the logic for this depends on the network where the messenger is
* being deployed. * being deployed.
*
* @return Whether the message is coming from the other messenger.
*/ */
function _isOtherMessenger() internal view virtual returns (bool); function _isOtherMessenger() internal view virtual returns (bool);
/**
* @notice Checks whether a given call target is a system address that could cause the
* messenger to peform an unsafe action. This is NOT a mechanism for blocking user
* addresses. This is ONLY used to prevent the execution of messages to specific
* system addresses that could cause security issues, e.g., having the
* CrossDomainMessenger send messages to itself.
*
* @param _target Address of the contract to check.
*
* @return Whether or not the address is an unsafe system address.
*/
function _isUnsafeTarget(address _target) internal view virtual returns (bool);
} }
...@@ -45,6 +45,11 @@ const config: HardhatUserConfig = { ...@@ -45,6 +45,11 @@ const config: HardhatUserConfig = {
url: process.env.L1_RPC || '', url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero], accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
}, },
'alpha-1': {
chainId: 5,
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
},
deployer: { deployer: {
chainId: Number(process.env.CHAIN_ID), chainId: Number(process.env.CHAIN_ID),
url: process.env.L1_RPC || '', url: process.env.L1_RPC || '',
......
...@@ -15,6 +15,15 @@ const main = async () => { ...@@ -15,6 +15,15 @@ const main = async () => {
const artifactPaths = glob const artifactPaths = glob
.sync(`${contractArtifactsFolder}/**/*.json`) .sync(`${contractArtifactsFolder}/**/*.json`)
.filter((match) => {
return [
'artifacts/contracts/chugsplash',
'artifacts/contracts/L1',
'artifacts/contracts/L2',
'artifacts/contracts/libraries',
'artifacts/contracts/standards',
].some((folder) => match.includes(folder))
})
.filter((match) => { .filter((match) => {
// Filter out the debug outputs. // Filter out the debug outputs.
return !match.endsWith('.dbg.json') return !match.endsWith('.dbg.json')
......
...@@ -191,4 +191,11 @@ export const BRIDGE_ADAPTER_DATA: { ...@@ -191,4 +191,11 @@ export const BRIDGE_ADAPTER_DATA: {
l2Bridge: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65' as const, l2Bridge: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65' as const,
}, },
}, },
[L2ChainID.OPTIMISM_GOERLI]: {
DAI: {
Adapter: DAIBridgeAdapter,
l1Bridge: '0x05a388Db09C2D44ec0b00Ee188cD42365c42Df23' as const,
l2Bridge: '0x467194771dAe2967Aef3ECbEDD3Bf9a310C76C65' as const,
},
},
} }
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
> **Note** the following assumes a single sequencer and batcher. In the future, the design will be adapted to > **Note** the following assumes a single sequencer and batcher. In the future, the design will be adapted to
> accomodate multiple such entities. > accomodate multiple such entities.
[L2 chain derivation][g-derivation] — deriving L2 [blocks][g-block] from L1 data — is one of the main responsability of [L2 chain derivation][g-derivation] — deriving L2 [blocks][g-block] from L1 data — is one of the main responsibility of
the [rollup node][g-rollup-node], both in validator mode, and in sequencer mode (where derivation acts as a sanity check the [rollup node][g-rollup-node], both in validator mode, and in sequencer mode (where derivation acts as a sanity check
on sequencing, and enables detecting L1 chain [re-organizations][g-reorg]). on sequencing, and enables detecting L1 chain [re-organizations][g-reorg]).
......
...@@ -218,7 +218,7 @@ Additionally, the first block in the window defines the [depositing transactions ...@@ -218,7 +218,7 @@ Additionally, the first block in the window defines the [depositing transactions
A sequencing epoch is sequential range of L2 blocks derived from a [sequencing window](#sequencing-window) of L1 blocks. A sequencing epoch is sequential range of L2 blocks derived from a [sequencing window](#sequencing-window) of L1 blocks.
Each epoch is identified by an epoch number, which is equal to the block number number of the first L1 block in the Each epoch is identified by an epoch number, which is equal to the block number of the first L1 block in the
sequencing window. sequencing window.
Epochs can have variable size, subject to some constraints. See the [L2 chain derivation specification][derivation-spec] Epochs can have variable size, subject to some constraints. See the [L2 chain derivation specification][derivation-spec]
...@@ -279,7 +279,7 @@ There are two kinds of deposited transactions: ...@@ -279,7 +279,7 @@ There are two kinds of deposited transactions:
An *L1 attributes deposited transaction* is [deposited transaction][deposited] that is used to register the L1 block An *L1 attributes deposited transaction* is [deposited transaction][deposited] that is used to register the L1 block
attributes (number, timestamp, ...) on L2 via a call to the [L1 Attributes Predeployed Contract][l1-attr-predeploy]. attributes (number, timestamp, ...) on L2 via a call to the [L1 Attributes Predeployed Contract][l1-attr-predeploy].
That contract can then be used to read the the attributes of the L1 block corresponding to the current L2 block. That contract can then be used to read the attributes of the L1 block corresponding to the current L2 block.
L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the L1 attributes deposited transactions are specified in the [L1 Attributes Deposit][l1-attributes-tx-spec] section of the
deposits specification. deposits specification.
...@@ -419,7 +419,7 @@ number](#sequencing-epoch) and an L2 block timestamp (which can trivially be con ...@@ -419,7 +419,7 @@ number](#sequencing-epoch) and an L2 block timestamp (which can trivially be con
block time is constant). block time is constant).
Sequencer batches are part of the [L2 derivation inputs][deriv-inputs]. Each batch represents the inputs needed to build Sequencer batches are part of the [L2 derivation inputs][deriv-inputs]. Each batch represents the inputs needed to build
**one** L2 block (given the existing L2 chain state) — excepted for the fist block of each epoch, which also needs **one** L2 block (given the existing L2 chain state) — except for the first block of each epoch, which also needs
information about deposits (cf. the section on [L2 derivation inputs][deriv-inputs]). information about deposits (cf. the section on [L2 derivation inputs][deriv-inputs]).
## Channel ## Channel
...@@ -431,7 +431,7 @@ to group multiple batches together is simply to obtain a better compression rate ...@@ -431,7 +431,7 @@ to group multiple batches together is simply to obtain a better compression rate
costs. costs.
A channel can be split in [frames][channel-frame] in order to be transmitted via [batcher A channel can be split in [frames][channel-frame] in order to be transmitted via [batcher
transactions][batcher-transaction]. The reason to split a channel into frames is that a channel might too large to transactions][batcher-transaction]. The reason to split a channel into frames is that a channel might be too large to
include in a single batcher transaction. include in a single batcher transaction.
A channel is uniquely identified by its timestamp (UNIX time at which the channel was created) and a random value. See A channel is uniquely identified by its timestamp (UNIX time at which the channel was created) and a random value. See
......
...@@ -34,7 +34,7 @@ are part of later specification milestones. ...@@ -34,7 +34,7 @@ are part of later specification milestones.
## Proposing L2 Output Commitments ## Proposing L2 Output Commitments
The proposer's role is to construct and submit output roots, which are commitments made on a configurable interval, The proposer's role is to construct and submit output roots, which are commitments made on a configurable interval,
to the `L2OutputOracle` contract running on L2. It does this by running the [L2 output proposer](../op-proposer/), to the `L2OutputOracle` contract running on L1. It does this by running the [L2 output proposer](../op-proposer/),
a service which periodically queries the rollup node's a service which periodically queries the rollup node's
[`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived [`optimism_outputAtBlock` rpc method](./rollup-node.md#l2-output-rpc-method) for the latest output root derived
from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is from the latest [finalized](rollup-node.md#finalization-guarantees) L1 block. The construction of this output root is
......
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