Commit dad10877 authored by Maurelian's avatar Maurelian Committed by GitHub

feat: Isthmus Contracts (#12746)

* feat: Isthmus Contracts work squashed

remove unused import

fix: IOptimismMintableERC721 interface

feat: move semver out of abstract OptimismMintableERC20Factory

Also add spacer after _initialized/ing

fix: Initializer check in DeployOPChain

fix: CrossDomainOwnable3 test

feat: update semver-lock

feat: Add systemConfigAdmin to deploy-config

fix: IL1BlockInterop iface

fix: update devnetL1-template

fix: casing on systemConfigFeeAdmin

feat: update ConfigType names

feat: rename setHolocene to setL1BlockValuesIsthmus

feat: refine setL1BLockValuesIsthmus to read fee vault config directly from getters.

fix: read remoteChainId from ERC721 Factory, not Bridge

feat: Update test_setL1BlockValuesIsthmus_isDepositor_succeeds to compare with cfg

feat: use setIsthmus()

* debug: Add fee admin to intent

* fix: fee vault immutable checks no longer necessary

* fix: TestConfigDataMarshalUnmarshal

* fix: immutable check for L2ProxyAdmin owner

* fix: SystemConfigFeeAdmin naming in opchain.go

* feat: op-deployer - get SystemConfigFeeAdmin from intent.Roles

* remove dead comments

* feat: resolve feeAdmin setting todo coment

* feat: move unsafeBLockSigner into SystemConfig.Roles struct

* feat: move batcherHash into SystemConfig.Roles struct

* fix: Add missing feeAdmin setter in DeployOpChain test

* fix: SystemConfig.init in specs

* feat: resolve todo

* feat: resolve some todos

* feat: Natspec in StaticConfig

* feat: resolve some todos

* fix: test_getConfigRoundtripGasPayingToken_succeeds with normalizeSmallString

* pre-pr

* test: Implement roll and reset prevBought gas in SystemConfig Test's cleanStorageAndInit()

* feat: Add natspec on SystemConfig.Roles

* feat: Fix all incomplete @notice natspec comments

* feat: systemConfigFeeAdmin name in opcm

* rebuild snapshots

* Add ArtifactsFromURL utility

* add configurability to createEnv

* clean up env.go

* fix apply test

* fix: TestInteropDeployment

* fix: TestApplyExistingOPCM

* fix: unchecked return on checkImmutable

* fix: goimports env.go

* fix: Add devkey for SystemConfigFeeAdmin

* fix: TestInteropDeployment

* fix: TestInteropDevRecipe

* feat: use base CDM interface in L1Block

* feat: configure L1 Block config values in L2Genesis

* feat: document Isthmus upgrade transactions on `setIsthmus()`

* semver fixes

* feat: L2 Genesis with cheated config in L1Block

* ok: how'd those warnings get in there in the first place?

* chore: update semver-lock

* works

* allocs build, cfg calls commented out cuz they fail

* fix: read DeployConfig before it gets deleted

* fix: test_allocs_size

* fix: restore l1 deps

* fix: test_getConfigRoundtripGasPayingToken_succeeds disallow eth address

* fix: update test_proveWithdrawalTransaction_benchmark

Unclear why this cost changed?

* feat: Add Isthmus to Config.sol

* feat: hoist L1Block population above allocs writes

* chore: delete debug logs

* WIP: update SystemConfig bindings and go usage

* fix: go linting

* feat: deposit setGasPayingToken as first call in SystemConfig.init

* semver lock

* TODO in L2Genesis

* chore: semver

* fix: Remove outdated comments

* feat: extract logic into _setNetworkConfig()

* test: Add total gas usage test

* remove dead comment

* ci: reduce heavy fuzz runs temporarily

---------
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
parent 3952e601
......@@ -131,7 +131,7 @@ rules:
- pattern-not: require($ERR);
- focus-metavariable: $ERR
- pattern-not-regex: \"(\w+:\s[^"]+)\"
- pattern-not-regex: string\.concat\(\"(\w+:\s[^"]+)\"\,[^"]+\)
- pattern-not-regex: string\.concat\(\"(\w+:\s)\"[^)]+\)
- pattern-not-regex: \"([a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+)\"
- pattern-not-regex: \"([a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+)\"
paths:
......@@ -152,7 +152,7 @@ rules:
- pattern-not: revert $ERR(...);
- focus-metavariable: $MSG
- pattern-not-regex: \"(\w+:\s[^"]+)\"
- pattern-not-regex: string\.concat\(\"(\w+:\s[^"]+)\"\,[^"]+\)
- pattern-not-regex: string\.concat\(\"(\w+:\s)\"[^)]+\)
- pattern-not-regex: \"([a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+)\"
- pattern-not-regex: \"([a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+-[a-zA-Z0-9\s]+)\"
paths:
......
......@@ -497,6 +497,9 @@ contract SemgrepTest__sol_style_malformed_require {
)
);
// ok: sol-style-malformed-require
require(result.length > 0, string.concat("ForgeArtifacts: ", _contractName, "is not initializable"));
// ruleid: sol-style-malformed-require
require(cond, "MyContract: ");
......@@ -541,6 +544,9 @@ contract SemgrepTest__sol_style_malformed_revert {
)
);
// ok: sol-style-malformed-revert
revert(string.concat("ForgeArtifacts: ", _contractName, "is not initializable"));
// ruleid: sol-style-malformed-revert
revert("MyContract: ");
......
......@@ -24,7 +24,7 @@ parser.add_argument('--allocs', help='Only create the allocs and exit', type=boo
log = logging.getLogger()
# Global constants
FORKS = ["delta", "ecotone", "fjord", "granite", "holocene"]
FORKS = ["delta", "ecotone", "fjord", "granite", "holocene", "isthmus"]
# Global environment variables
DEVNET_NO_BUILD = os.getenv('DEVNET_NO_BUILD') == "true"
......
......@@ -158,6 +158,8 @@ const (
SequencerFeeVaultRecipientRole ChainOperatorRole = 9
// SystemConfigOwner is the key that can make SystemConfig changes.
SystemConfigOwner ChainOperatorRole = 10
// SystemConfigFeeAdmin is the key that can make SystemConfigFee changes.
SystemConfigFeeAdmin ChainOperatorRole = 11
)
func (role ChainOperatorRole) String() string {
......@@ -184,6 +186,8 @@ func (role ChainOperatorRole) String() string {
return "sequencer-fee-vault-recipient"
case SystemConfigOwner:
return "system-config-owner"
case SystemConfigFeeAdmin:
return "system-config-fee-admin"
default:
return fmt.Sprintf("unknown-operator-%d", uint64(role))
}
......
......@@ -286,6 +286,9 @@ type OperatorDeployConfig struct {
// BatchSenderAddress represents the initial sequencer account that authorizes batches.
// Transactions sent from this account to the batch inbox address are considered valid.
BatchSenderAddress common.Address `json:"batchSenderAddress"`
// SystemConfigfeeAdmin is the address of the account that has the ability to set the fee parameters.
SystemConfigfeeAdmin common.Address `json:"systemConfigFeeAdmin"`
}
var _ ConfigChecker = (*OperatorDeployConfig)(nil)
......
......@@ -22,6 +22,7 @@
"l1GenesisBlockGasLimit": "0x1c9c380",
"l1GenesisBlockDifficulty": "0x1",
"finalSystemOwner": "0xbcd4042de499d14e55001ccbb24a551f3b954096",
"systemConfigFeeAdmin": "0xbcd4042de499d14e55001ccbb24a551f3b954096",
"superchainConfigGuardian": "0x0000000000000000000000000000000000000112",
"finalizationPeriodSeconds": 2,
"l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
......
......@@ -75,6 +75,7 @@ type L2Config struct {
Proposer common.Address
Challenger common.Address
SystemConfigOwner common.Address
SystemConfigFeeAdmin common.Address
genesis.L2InitializationConfig
Prefund map[common.Address]*big.Int
SaltMixer string
......
......@@ -200,7 +200,8 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
l1Host.SetTxOrigin(cfg.Deployer)
output, err := opcm.DeployOPChainV160(l1Host, opcm.DeployOPChainInputV160{
output, err := opcm.DeployOPChainIsthmus(l1Host, opcm.DeployOPChainInputIsthmus{
DeployOPChainInputV160: opcm.DeployOPChainInputV160{
OpChainProxyAdminOwner: cfg.ProxyAdminOwner,
SystemConfigOwner: cfg.SystemConfigOwner,
Batcher: cfg.BatchSenderAddress,
......@@ -218,7 +219,8 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
DisputeMaxGameDepth: cfg.DisputeMaxGameDepth,
DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration},
SystemConfigFeeAdmin: cfg.SystemConfigFeeAdmin,
})
if err != nil {
return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err)
......
......@@ -178,12 +178,17 @@ func InteropL2DevConfig(l1ChainID, l2ChainID uint64, addrs devkeys.Addresses) (*
if err != nil {
return nil, err
}
systemConfigFeeAdmin, err := addrs.Address(chainOps(devkeys.SystemConfigFeeAdmin))
if err != nil {
return nil, err
}
l2Cfg := &L2Config{
Deployer: deployer,
Proposer: proposer,
Challenger: challenger,
SystemConfigOwner: systemConfigOwner,
SystemConfigFeeAdmin: systemConfigFeeAdmin,
L2InitializationConfig: genesis.L2InitializationConfig{
DevDeployConfig: genesis.DevDeployConfig{
FundDevAccounts: true,
......
......@@ -12,6 +12,7 @@ import (
"time"
altda "github.com/ethereum-optimism/optimism/op-alt-da"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect"
"github.com/ethereum-optimism/optimism/op-node/rollup"
......@@ -125,7 +126,7 @@ func TestEndToEndApply(t *testing.T) {
})
require.NoError(t, err)
env, bundle, _ := createEnv(t, lgr, l1Client, bcaster, deployerAddr)
env, bundle, _ := createEnv(t, lgr, l1Client, bcaster, deployerAddr, localArtifactsFactory, localArtifactsFactory)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
cg := ethClientCodeGetter(ctx, l1Client)
......@@ -145,7 +146,7 @@ func TestEndToEndApply(t *testing.T) {
t.Run("subsequent chain", func(t *testing.T) {
// create a new environment with wiped state to ensure we can continue using the
// state from the previous deployment
env, bundle, _ = createEnv(t, lgr, l1Client, bcaster, deployerAddr)
env, bundle, _ = createEnv(t, lgr, l1Client, bcaster, deployerAddr, localArtifactsFactory, localArtifactsFactory)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID2))
require.NoError(t, deployer.ApplyPipeline(
......@@ -207,7 +208,17 @@ func TestApplyExistingOPCM(t *testing.T) {
})
require.NoError(t, err)
env, bundle, _ := createEnv(t, lgr, l1Client, bcaster, deployerAddr)
// use the l2 contracts here because the v1.7.0 contracts are compatible with the v1.6.0
// contracts and createEnv uses the same artifacts for both L1/L2 in the bundle.
env, bundle, _ := createEnv(
t,
lgr,
l1Client,
bcaster,
deployerAddr,
taggedArtifactsFactory(standard.DefaultL1ContractsTag),
taggedArtifactsFactory(standard.DefaultL2ContractsTag),
)
intent, st := newIntent(
t,
......@@ -379,7 +390,8 @@ func TestProofParamOverrides(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
checkImmutable(t, allocs, tt.address, tt.caster(t, intent.GlobalDeployOverrides[tt.name]))
err := checkImmutable(t, allocs, tt.address, tt.caster(t, intent.GlobalDeployOverrides[tt.name]))
require.NoError(t, err)
})
}
}
......@@ -403,9 +415,9 @@ func TestInteropDeployment(t *testing.T) {
chainState := st.Chains[0]
depManagerSlot := common.HexToHash("0x1708e077affb93e89be2665fb0fb72581be66f84dc00d25fed755ae911905b1c")
checkImmutable(t, st.L1StateDump.Data.Accounts, st.ImplementationsDeployment.SystemConfigImplAddress, depManagerSlot)
proxyAdminOwnerHash := common.BytesToHash(intent.Chains[0].Roles.SystemConfigOwner.Bytes())
checkStorageSlot(t, st.L1StateDump.Data.Accounts, chainState.SystemConfigProxyAddress, depManagerSlot, proxyAdminOwnerHash)
require.NoError(t, checkImmutable(t, st.L1StateDump.Data.Accounts, st.ImplementationsDeployment.SystemConfigImplAddress, depManagerSlot))
systemConfigOwnerHash := common.BytesToHash(intent.Chains[0].Roles.SystemConfigOwner.Bytes())
checkStorageSlot(t, st.L1StateDump.Data.Accounts, chainState.SystemConfigProxyAddress, depManagerSlot, systemConfigOwnerHash)
}
func TestAltDADeployment(t *testing.T) {
......@@ -512,7 +524,7 @@ func TestInvalidL2Genesis(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr, localArtifactsFactory, localArtifactsFactory)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
......@@ -546,27 +558,42 @@ func setupGenesisChain(t *testing.T) (*pipeline.Env, pipeline.ArtifactsBundle, *
loc, _ := testutil.LocalArtifacts(t)
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr, localArtifactsFactory, localArtifactsFactory)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
return env, bundle, intent, st
}
type artifactsFactory func(t *testing.T) (*artifacts.Locator, foundry.StatDirFs)
func localArtifactsFactory(t *testing.T) (*artifacts.Locator, foundry.StatDirFs) {
return testutil.LocalArtifacts(t)
}
func taggedArtifactsFactory(tag string) artifactsFactory {
return func(t *testing.T) (*artifacts.Locator, foundry.StatDirFs) {
return testutil.ArtifactsFromURL(t, fmt.Sprintf("tag://%s", tag))
}
}
func createEnv(
t *testing.T,
lgr log.Logger,
l1Client *ethclient.Client,
bcaster broadcaster.Broadcaster,
deployerAddr common.Address,
l1Factory artifactsFactory,
l2Factory artifactsFactory,
) (*pipeline.Env, pipeline.ArtifactsBundle, *script.Host) {
_, artifactsFS := testutil.LocalArtifacts(t)
_, l1AFS := l1Factory(t)
_, l2AFS := l2Factory(t)
host, err := env.DefaultScriptHost(
bcaster,
lgr,
deployerAddr,
artifactsFS,
l1AFS,
0,
)
require.NoError(t, err)
......@@ -581,8 +608,8 @@ func createEnv(
}
bundle := pipeline.ArtifactsBundle{
L1: artifactsFS,
L2: artifactsFS,
L1: l1AFS,
L2: l2AFS,
}
return env, bundle, host
......@@ -635,6 +662,7 @@ func newChainIntent(t *testing.T, dk *devkeys.MnemonicDevKeys, l1ChainID *big.In
L1ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
L2ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
SystemConfigOwner: addrFor(t, dk, devkeys.SystemConfigOwner.Key(l1ChainID)),
SystemConfigFeeAdmin: addrFor(t, dk, devkeys.SystemConfigFeeAdmin.Key(l1ChainID)),
UnsafeBlockSigner: addrFor(t, dk, devkeys.SequencerP2PRole.Key(l1ChainID)),
Batcher: addrFor(t, dk, devkeys.BatcherRole.Key(l1ChainID)),
Proposer: addrFor(t, dk, devkeys.ProposerRole.Key(l1ChainID)),
......@@ -739,17 +767,20 @@ func validateOPChainDeployment(t *testing.T, cg codeGetter, st *state.State, int
alloc := chainState.Allocs.Data.Accounts
chainIntent := intent.Chains[i]
checkImmutableBehindProxy(t, alloc, predeploys.BaseFeeVaultAddr, chainIntent.BaseFeeVaultRecipient)
checkImmutableBehindProxy(t, alloc, predeploys.L1FeeVaultAddr, chainIntent.L1FeeVaultRecipient)
checkImmutableBehindProxy(t, alloc, predeploys.SequencerFeeVaultAddr, chainIntent.SequencerFeeVaultRecipient)
checkImmutableBehindProxy(t, alloc, predeploys.OptimismMintableERC721FactoryAddr, common.BigToHash(new(big.Int).SetUint64(intent.L1ChainID)))
// ownership slots
var addrAsSlot common.Hash
addrAsSlot.SetBytes(chainIntent.Roles.L1ProxyAdminOwner.Bytes())
// slot 0
ownerSlot := common.Hash{}
checkStorageSlot(t, alloc, predeploys.ProxyAdminAddr, ownerSlot, addrAsSlot)
// First try to read the owner from the bytecode, which is the situation with the
// Isthmus L2ProxyAdmin (on this commit).
if err := checkImmutableBehindProxy(t, alloc, predeploys.ProxyAdminAddr, common.HexToAddress("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001")); err != nil {
t.Logf("Warning: Failed to check immutable behind proxy for L2ProxyAdmin, falling back to <=v1.6.0 storage check")
// If the bytecode check fails, fall back to reading the owner from storage.
// Note however that the L2ProxyAdmin owner address here (0xe59a881b2626f948f56f509f180c32428585629a) comes from the chainIntent,
// and does not actually match the `owner()` of the L2ProxyAdmin contract deployed on Sepolia (0x2FC3ffc903729a0f03966b917003800B145F67F3).
// It seems the L2 state is locally constructed rather than pulled from an L2 RPC.
var L2ProxyAdminOwner common.Hash
L2ProxyAdminOwner.SetBytes(chainIntent.Roles.L2ProxyAdminOwner.Bytes())
checkStorageSlot(t, alloc, predeploys.ProxyAdminAddr, common.Hash{}, L2ProxyAdminOwner)
}
var defaultGovOwner common.Hash
defaultGovOwner.SetBytes(common.HexToAddress("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAdDEad").Bytes())
checkStorageSlot(t, alloc, predeploys.GovernanceTokenAddr, common.Hash{31: 0x0a}, defaultGovOwner)
......@@ -770,20 +801,23 @@ type bytesMarshaler interface {
Bytes() []byte
}
func checkImmutableBehindProxy(t *testing.T, allocations types.GenesisAlloc, proxyContract common.Address, thing bytesMarshaler) {
func checkImmutableBehindProxy(t *testing.T, allocations types.GenesisAlloc, proxyContract common.Address, thing bytesMarshaler) error {
implementationAddress := getEIP1967ImplementationAddress(t, allocations, proxyContract)
checkImmutable(t, allocations, implementationAddress, thing)
return checkImmutable(t, allocations, implementationAddress, thing)
}
func checkImmutable(t *testing.T, allocations types.GenesisAlloc, implementationAddress common.Address, thing bytesMarshaler) {
func checkImmutable(t *testing.T, allocations types.GenesisAlloc, implementationAddress common.Address, thing bytesMarshaler) error {
account, ok := allocations[implementationAddress]
require.True(t, ok, "%s not found in allocations", implementationAddress)
require.NotEmpty(t, account.Code, "%s should have code", implementationAddress)
require.True(
t,
bytes.Contains(account.Code, thing.Bytes()),
"%s code should contain %s immutable", implementationAddress, hex.EncodeToString(thing.Bytes()),
)
if !ok {
return fmt.Errorf("%s not found in allocations", implementationAddress)
}
if len(account.Code) == 0 {
return fmt.Errorf("%s should have code", implementationAddress)
}
if !bytes.Contains(account.Code, thing.Bytes()) {
return fmt.Errorf("%s code should contain %s immutable", implementationAddress, hex.EncodeToString(thing.Bytes()))
}
return nil
}
func checkStorageSlot(t *testing.T, allocs types.GenesisAlloc, address common.Address, slot common.Hash, expected common.Hash) {
......
......@@ -59,7 +59,7 @@ type opcmDeployInputV160 struct {
type opcmRolesIsthmus struct {
opcmRolesBase
FeeAdmin common.Address
SystemConfigFeeAdmin common.Address
}
type opcmDeployInputIsthmus struct {
......@@ -136,7 +136,7 @@ func DeployOPChainInputIsthmusDeployCalldata(input DeployOPChainInputIsthmus) an
return opcmDeployInputIsthmus{
Roles: opcmRolesIsthmus{
opcmRolesBase: v160Data.Roles,
FeeAdmin: input.SystemConfigFeeAdmin,
SystemConfigFeeAdmin: input.SystemConfigFeeAdmin,
},
opcmDeployInputBase: v160Data.opcmDeployInputBase,
}
......
......@@ -276,7 +276,7 @@ func makeDCIIsthmus(intent *state.Intent, thisIntent *state.ChainIntent, chainID
return opcm.DeployOPChainInputIsthmus{
DeployOPChainInputV160: dci,
SystemConfigFeeAdmin: common.Address{'D', 'E', 'A', 'D'},
SystemConfigFeeAdmin: thisIntent.Roles.SystemConfigFeeAdmin,
}, nil
}
......
......@@ -176,6 +176,8 @@ type ChainRoles struct {
SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"`
SystemConfigFeeAdmin common.Address `json:"systemConfigFeeAdmin" toml:"systemConfigFeeAdmin"`
UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"`
Batcher common.Address `json:"batcher" toml:"batcher"`
......@@ -199,6 +201,10 @@ func (c *ChainIntent) Check() error {
c.Roles.SystemConfigOwner = c.Roles.L1ProxyAdminOwner
}
if c.Roles.SystemConfigFeeAdmin == emptyAddress {
return fmt.Errorf("systemConfigFeeAdmin must be set")
}
if c.Roles.L2ProxyAdminOwner == emptyAddress {
return fmt.Errorf("l2ProxyAdminOwner must be set")
}
......
......@@ -3,31 +3,35 @@ package testutil
import (
"context"
"fmt"
"net/url"
"path"
"runtime"
"testing"
artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
op_service "github.com/ethereum-optimism/optimism/op-service"
"github.com/stretchr/testify/require"
)
func LocalArtifacts(t *testing.T) (*artifacts2.Locator, foundry.StatDirFs) {
func LocalArtifacts(t *testing.T) (*artifacts.Locator, foundry.StatDirFs) {
_, testFilename, _, ok := runtime.Caller(0)
require.Truef(t, ok, "failed to get test filename")
monorepoDir, err := op_service.FindMonorepoRoot(testFilename)
require.NoError(t, err)
artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts")
artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir))
require.NoError(t, err)
loc := &artifacts2.Locator{
URL: artifactsURL,
}
return ArtifactsFromURL(t, fmt.Sprintf("file://%s", artifactsDir))
}
func ArtifactsFromURL(t *testing.T, artifactsURLStr string) (*artifacts.Locator, foundry.StatDirFs) {
loc := new(artifacts.Locator)
require.NoError(t, loc.UnmarshalText([]byte(artifactsURLStr)))
artifactsFS, cleanupArtifacts, err := artifacts2.Download(context.Background(), loc, artifacts2.NoopDownloadProgressor)
progressor := artifacts.LogProgressor(testlog.Logger(t, log.LevelInfo))
artifactsFS, cleanupArtifacts, err := artifacts.Download(context.Background(), loc, progressor)
require.NoError(t, err)
t.Cleanup(func() {
_ = cleanupArtifacts()
......
This diff is collapsed.
......@@ -159,18 +159,21 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
require.NoError(t, err)
// Get existing parameters from SystemConfigProxy contract
owner, err := systemConfig.Owner(&bind.CallOpts{})
roles := bindings.SystemConfigRoles{}
roles.Owner, err = systemConfig.Owner(&bind.CallOpts{})
require.NoError(t, err)
roles.FeeAdmin, err = systemConfig.FeeAdmin(&bind.CallOpts{})
require.NoError(t, err)
roles.UnsafeBlockSigner, err = systemConfig.UnsafeBlockSigner(&bind.CallOpts{})
require.NoError(t, err)
roles.BatcherHash, err = systemConfig.BatcherHash(&bind.CallOpts{})
require.NoError(t, err)
basefeeScalar, err := systemConfig.BasefeeScalar(&bind.CallOpts{})
require.NoError(t, err)
blobbasefeeScalar, err := systemConfig.BlobbasefeeScalar(&bind.CallOpts{})
require.NoError(t, err)
batcherHash, err := systemConfig.BatcherHash(&bind.CallOpts{})
require.NoError(t, err)
gasLimit, err := systemConfig.GasLimit(&bind.CallOpts{})
require.NoError(t, err)
unsafeBlockSigner, err := systemConfig.UnsafeBlockSigner(&bind.CallOpts{})
require.NoError(t, err)
resourceConfig, err := systemConfig.ResourceConfig(&bind.CallOpts{})
require.NoError(t, err)
batchInbox, err := systemConfig.BatchInbox(&bind.CallOpts{})
......@@ -228,12 +231,10 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
waitForTx(t, tx, err, l1Client)
// Reinitialise with existing initializer values but with custom gas token set
tx, err = systemConfig.Initialize(deployerOpts, owner,
tx, err = systemConfig.Initialize(deployerOpts, roles,
basefeeScalar,
blobbasefeeScalar,
batcherHash,
gasLimit,
unsafeBlockSigner,
resourceConfig,
batchInbox,
addresses)
......
......@@ -4,14 +4,14 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm
GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5099)
GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531)
GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369280)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967420)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564398)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076613)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467098)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512802)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72664)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 367239)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2965379)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 560245)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4072288)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 462746)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3508450)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 70492)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68422)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68986)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155610)
\ No newline at end of file
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68366)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68930)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155655)
\ No newline at end of file
......@@ -27,6 +27,7 @@
"sequencerFeeVaultWithdrawalNetwork": 0,
"proxyAdminOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"finalSystemOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"systemConfigFeeAdmin": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"superchainConfigGuardian": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"finalizationPeriodSeconds": 2,
"fundDevAccounts": true,
......
{
"finalSystemOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"systemConfigFeeAdmin": "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
"superchainConfigGuardian": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"proxyAdminOwner": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"l1StartingBlockTag": "earliest",
......
......@@ -76,7 +76,9 @@ runs = 256
depth = 32
[profile.ciheavy]
fuzz = { runs = 20000 }
# temp reduce fuzz runs for 1 pr
# fuzz = { runs = 20000 }
fuzz = { runs = 200 }
[profile.ciheavy.invariant]
runs = 128
......
......@@ -47,7 +47,6 @@ abstract contract Artifacts {
/// @notice Setup function. The arguments here
function setUp() public virtual {
deploymentOutfile = Config.deploymentOutfile();
console.log("Writing artifact to %s", deploymentOutfile);
ForgeArtifacts.ensurePath(deploymentOutfile);
uint256 chainId = Config.chainID();
......@@ -183,7 +182,6 @@ abstract contract Artifacts {
/// @param _name The name of the deployment.
/// @param _deployed The address of the deployment.
function save(string memory _name, address _deployed) public {
console.log("Saving %s: %s", _name, _deployed);
if (bytes(_name).length == 0) {
revert InvalidDeployment("EmptyName");
}
......
......@@ -155,7 +155,7 @@ contract Deploy is Deployer {
DelayedWETH: getAddress("DelayedWETHProxy"),
PermissionedDelayedWETH: getAddress("PermissionedDelayedWETHProxy"),
AnchorStateRegistry: getAddress("AnchorStateRegistryProxy"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
OptimismMintableERC20Factory: getAddress("L1OptimismMintableERC20FactoryProxy"),
OptimismPortal: getAddress("OptimismPortalProxy"),
OptimismPortal2: getAddress("OptimismPortalProxy"),
SystemConfig: getAddress("SystemConfigProxy"),
......@@ -176,7 +176,7 @@ contract Deploy is Deployer {
DelayedWETH: getAddress("DelayedWETH"),
PermissionedDelayedWETH: getAddress("PermissionedDelayedWETH"),
AnchorStateRegistry: getAddress("AnchorStateRegistry"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20Factory"),
OptimismMintableERC20Factory: getAddress("L1OptimismMintableERC20Factory"),
OptimismPortal: getAddress("OptimismPortal"),
OptimismPortal2: getAddress("OptimismPortal2"),
SystemConfig: getAddress("SystemConfig"),
......@@ -398,7 +398,9 @@ contract Deploy is Deployer {
}
save("L1CrossDomainMessenger", address(dio.l1CrossDomainMessengerImpl()));
// Save under both names for backwards compatibility
save("OptimismMintableERC20Factory", address(dio.optimismMintableERC20FactoryImpl()));
save("L1OptimismMintableERC20Factory", address(dio.optimismMintableERC20FactoryImpl()));
save("SystemConfig", address(dio.systemConfigImpl()));
save("L1StandardBridge", address(dio.l1StandardBridgeImpl()));
save("L1ERC721Bridge", address(dio.l1ERC721BridgeImpl()));
......@@ -413,7 +415,7 @@ contract Deploy is Deployer {
save("OPContractsManager", address(dio.opcmImpl()));
Types.ContractSet memory contracts = _impls();
ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
......@@ -456,7 +458,9 @@ contract Deploy is Deployer {
save("AddressManager", address(deployOutput.addressManager));
save("L1ERC721BridgeProxy", address(deployOutput.l1ERC721BridgeProxy));
save("SystemConfigProxy", address(deployOutput.systemConfigProxy));
// Save under both names for backwards compatibility
save("OptimismMintableERC20FactoryProxy", address(deployOutput.optimismMintableERC20FactoryProxy));
save("L1OptimismMintableERC20FactoryProxy", address(deployOutput.optimismMintableERC20FactoryProxy));
save("L1StandardBridgeProxy", address(deployOutput.l1StandardBridgeProxy));
save("L1CrossDomainMessengerProxy", address(deployOutput.l1CrossDomainMessengerProxy));
......@@ -823,12 +827,15 @@ contract Deploy is Deployer {
_data: abi.encodeCall(
ISystemConfig.initialize,
(
cfg.finalSystemOwner(),
ISystemConfig.Roles({
owner: cfg.finalSystemOwner(),
feeAdmin: cfg.systemConfigFeeAdmin(),
unsafeBlockSigner: cfg.p2pSequencerAddress(),
batcherHash: batcherHash
}),
cfg.basefeeScalar(),
cfg.blobbasefeeScalar(),
batcherHash,
uint64(cfg.l2GenesisBlockGasLimit()),
cfg.p2pSequencerAddress(),
Constants.DEFAULT_RESOURCE_CONFIG(),
cfg.batchInboxAddress(),
ISystemConfig.Addresses({
......@@ -837,7 +844,7 @@ contract Deploy is Deployer {
l1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
disputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"),
optimismPortal: mustGetAddress("OptimismPortalProxy"),
optimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
optimismMintableERC20Factory: mustGetAddress("L1OptimismMintableERC20FactoryProxy"),
gasPayingToken: customGasTokenAddress
})
)
......@@ -1264,7 +1271,8 @@ contract Deploy is Deployer {
batcher: cfg.batchSenderAddress(),
unsafeBlockSigner: cfg.p2pSequencerAddress(),
proposer: cfg.l2OutputOracleProposer(),
challenger: cfg.l2OutputOracleChallenger()
challenger: cfg.l2OutputOracleChallenger(),
systemConfigFeeAdmin: cfg.systemConfigFeeAdmin()
}),
basefeeScalar: cfg.basefeeScalar(),
blobBasefeeScalar: cfg.blobbasefeeScalar(),
......
......@@ -86,6 +86,7 @@ contract DeployConfig is Script {
uint256 public daResolveWindow;
uint256 public daBondSize;
uint256 public daResolverRefundPercentage;
address public systemConfigFeeAdmin;
bool public useCustomGasToken;
address public customGasTokenAddress;
......@@ -101,6 +102,7 @@ contract DeployConfig is Script {
}
finalSystemOwner = stdJson.readAddress(_json, "$.finalSystemOwner");
systemConfigFeeAdmin = stdJson.readAddress(_json, "$.systemConfigFeeAdmin");
superchainConfigGuardian = stdJson.readAddress(_json, "$.superchainConfigGuardian");
l1ChainID = stdJson.readUint(_json, "$.l1ChainID");
l2ChainID = stdJson.readUint(_json, "$.l2ChainID");
......
......@@ -29,7 +29,8 @@ import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol";
import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol";
import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol";
import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol";
import { IL1OptimismMintableERC20Factory as IOptimismMintableERC20Factory } from
"src/L1/interfaces/IL1OptimismMintableERC20Factory.sol";
import { OPContractsManagerInterop } from "src/L1/OPContractsManagerInterop.sol";
import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol";
......@@ -370,19 +371,19 @@ contract DeployImplementationsOutput is BaseDeployIO {
DeployUtils.assertInitialized({ _contractAddress: address(systemConfig), _slot: 0, _offset: 0 });
require(systemConfig.owner() == address(0xdead), "SYSCON-10");
require(systemConfig.owner() == address(0), "SYSCON-10");
require(systemConfig.overhead() == 0, "SYSCON-20");
require(systemConfig.scalar() == uint256(0x01) << 248, "SYSCON-30");
require(systemConfig.scalar() == 0, "SYSCON-30");
require(systemConfig.basefeeScalar() == 0, "SYSCON-40");
require(systemConfig.blobbasefeeScalar() == 0, "SYSCON-50");
require(systemConfig.batcherHash() == bytes32(0), "SYSCON-60");
require(systemConfig.gasLimit() == 1, "SYSCON-70");
require(systemConfig.gasLimit() == 0, "SYSCON-70");
require(systemConfig.unsafeBlockSigner() == address(0), "SYSCON-80");
IResourceMetering.ResourceConfig memory resourceConfig = systemConfig.resourceConfig();
require(resourceConfig.maxResourceLimit == 1, "SYSCON-90");
require(resourceConfig.elasticityMultiplier == 1, "SYSCON-100");
require(resourceConfig.baseFeeMaxChangeDenominator == 2, "SYSCON-110");
require(resourceConfig.maxResourceLimit == 0, "SYSCON-90");
require(resourceConfig.elasticityMultiplier == 0, "SYSCON-100");
require(resourceConfig.baseFeeMaxChangeDenominator == 0, "SYSCON-110");
require(resourceConfig.systemTxMaxGas == 0, "SYSCON-120");
require(resourceConfig.minimumBaseFee == 0, "SYSCON-130");
require(resourceConfig.maximumBaseFee == 0, "SYSCON-140");
......@@ -400,7 +401,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
function assertValidL1CrossDomainMessengerImpl(DeployImplementationsInput) internal view {
IL1CrossDomainMessenger messenger = l1CrossDomainMessengerImpl();
DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 0, _offset: 20 });
DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 250, _offset: 0 });
require(address(messenger.OTHER_MESSENGER()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-10");
require(address(messenger.otherMessenger()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-20");
......@@ -408,14 +409,15 @@ contract DeployImplementationsOutput is BaseDeployIO {
require(address(messenger.portal()) == address(0), "L1xDM-40");
require(address(messenger.superchainConfig()) == address(0), "L1xDM-50");
bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204)));
require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60");
// TODO: vm.expectRevert is not supported by op-chain-ops, so we can't check this yet.
// vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
// messenger.xDomainMessageSender();
}
function assertValidL1ERC721BridgeImpl(DeployImplementationsInput) internal view {
IL1ERC721Bridge bridge = l1ERC721BridgeImpl();
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(bridge) });
require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_ERC721_BRIDGE, "L721B-10");
require(address(bridge.otherBridge()) == Predeploys.L2_ERC721_BRIDGE, "L721B-20");
......@@ -427,7 +429,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
function assertValidL1StandardBridgeImpl(DeployImplementationsInput) internal view {
IL1StandardBridge bridge = l1StandardBridgeImpl();
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 49, _offset: 0 });
require(address(bridge.MESSENGER()) == address(0), "L1SB-10");
require(address(bridge.messenger()) == address(0), "L1SB-20");
......@@ -439,7 +441,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
function assertValidOptimismMintableERC20FactoryImpl(DeployImplementationsInput) internal view {
IOptimismMintableERC20Factory factory = optimismMintableERC20FactoryImpl();
DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 51, _offset: 0 });
require(address(factory.BRIDGE()) == address(0), "MERC20F-10");
require(address(factory.bridge()) == address(0), "MERC20F-20");
......@@ -788,7 +790,7 @@ contract DeployImplementations is Script {
vm.broadcast(msg.sender);
impl = IOptimismMintableERC20Factory(
DeployUtils.create1({
_name: "OptimismMintableERC20Factory",
_name: "L1OptimismMintableERC20Factory",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ()))
})
);
......@@ -796,7 +798,7 @@ contract DeployImplementations is Script {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "OptimismMintableERC20FactoryImpl");
vm.label(address(impl), "L1OptimismMintableERC20FactoryImpl");
_dio.set(_dio.optimismMintableERC20FactoryImpl.selector, address(impl));
}
......
......@@ -38,6 +38,7 @@ import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimis
contract DeployOPChainInput is BaseDeployIO {
address internal _opChainProxyAdminOwner;
address internal _systemConfigOwner;
address internal _systemConfigFeeAdmin;
address internal _batcher;
address internal _unsafeBlockSigner;
address internal _proposer;
......@@ -64,6 +65,7 @@ contract DeployOPChainInput is BaseDeployIO {
require(_addr != address(0), "DeployOPChainInput: cannot set zero address");
if (_sel == this.opChainProxyAdminOwner.selector) _opChainProxyAdminOwner = _addr;
else if (_sel == this.systemConfigOwner.selector) _systemConfigOwner = _addr;
else if (_sel == this.systemConfigFeeAdmin.selector) _systemConfigFeeAdmin = _addr;
else if (_sel == this.batcher.selector) _batcher = _addr;
else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr;
else if (_sel == this.proposer.selector) _proposer = _addr;
......@@ -123,6 +125,11 @@ contract DeployOPChainInput is BaseDeployIO {
return _systemConfigOwner;
}
function systemConfigFeeAdmin() public view returns (address) {
require(_systemConfigFeeAdmin != address(0), "DeployOPChainInput: not set");
return _systemConfigFeeAdmin;
}
function batcher() public view returns (address) {
require(_batcher != address(0), "DeployOPChainInput: not set");
return _batcher;
......@@ -355,7 +362,8 @@ contract DeployOPChain is Script {
batcher: _doi.batcher(),
unsafeBlockSigner: _doi.unsafeBlockSigner(),
proposer: _doi.proposer(),
challenger: _doi.challenger()
challenger: _doi.challenger(),
systemConfigFeeAdmin: _doi.systemConfigFeeAdmin()
});
OPContractsManager.DeployInput memory deployInput = OPContractsManager.DeployInput({
roles: roles,
......@@ -572,7 +580,7 @@ contract DeployOPChain is Script {
function assertValidL1CrossDomainMessenger(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IL1CrossDomainMessenger messenger = _doo.l1CrossDomainMessengerProxy();
DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 0, _offset: 20 });
DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 250, _offset: 0 });
require(address(messenger.OTHER_MESSENGER()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-10");
require(address(messenger.otherMessenger()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-20");
......@@ -581,15 +589,16 @@ contract DeployOPChain is Script {
require(address(messenger.portal()) == address(_doo.optimismPortalProxy()), "L1xDM-40");
require(address(messenger.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1xDM-50");
bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204)));
require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60");
// TODO: vm.expectRevert is not supported by op-chain-ops, so we can't check this yet.
// vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
// messenger.xDomainMessageSender();
}
function assertValidL1StandardBridge(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IL1StandardBridge bridge = _doo.l1StandardBridgeProxy();
IL1CrossDomainMessenger messenger = _doo.l1CrossDomainMessengerProxy();
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 49, _offset: 0 });
require(address(bridge.MESSENGER()) == address(messenger), "L1SB-10");
require(address(bridge.messenger()) == address(messenger), "L1SB-20");
......@@ -601,7 +610,7 @@ contract DeployOPChain is Script {
function assertValidOptimismMintableERC20Factory(DeployOPChainInput, DeployOPChainOutput _doo) internal {
IOptimismMintableERC20Factory factory = _doo.optimismMintableERC20FactoryProxy();
DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 51, _offset: 0 });
require(factory.BRIDGE() == address(_doo.l1StandardBridgeProxy()), "MERC20F-10");
require(factory.bridge() == address(_doo.l1StandardBridgeProxy()), "MERC20F-20");
......@@ -610,7 +619,7 @@ contract DeployOPChain is Script {
function assertValidL1ERC721Bridge(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IL1ERC721Bridge bridge = _doo.l1ERC721BridgeProxy();
DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 });
DeployUtils.assertInitialized({ _contractAddress: address(bridge) });
require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_ERC721_BRIDGE, "L721B-10");
require(address(bridge.otherBridge()) == Predeploys.L2_ERC721_BRIDGE, "L721B-20");
......
......@@ -359,6 +359,7 @@ contract DeploySuperchain is Script {
function deployAndInitializeSuperchainConfig(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public {
address guardian = _dsi.guardian();
address upgrader = _dsi.superchainProxyAdminOwner();
bool paused = _dsi.paused();
IProxyAdmin superchainProxyAdmin = _dso.superchainProxyAdmin();
......@@ -376,7 +377,7 @@ contract DeploySuperchain is Script {
superchainProxyAdmin.upgradeAndCall(
payable(address(superchainConfigProxy)),
address(superchainConfigImpl),
abi.encodeCall(ISuperchainConfig.initialize, (guardian, paused))
abi.encodeCall(ISuperchainConfig.initialize, (guardian, upgrader, paused))
);
vm.stopBroadcast();
......
......@@ -34,10 +34,11 @@ enum Fork {
ECOTONE,
FJORD,
GRANITE,
HOLOCENE
HOLOCENE,
ISTHMUS
}
Fork constant LATEST_FORK = Fork.HOLOCENE;
Fork constant LATEST_FORK = Fork.ISTHMUS;
library ForkUtils {
function toString(Fork _fork) internal pure returns (string memory) {
......@@ -53,6 +54,8 @@ library ForkUtils {
return "granite";
} else if (_fork == Fork.HOLOCENE) {
return "holocene";
} else if (_fork == Fork.ISTHMUS) {
return "isthmus";
} else {
return "unknown";
}
......@@ -168,6 +171,8 @@ library Config {
return Fork.GRANITE;
} else if (forkHash == keccak256(bytes("holocene"))) {
return Fork.HOLOCENE;
} else if (forkHash == keccak256(bytes("isthmus"))) {
return Fork.ISTHMUS;
} else {
revert(string.concat("Config: unknown fork: ", forkStr));
}
......
......@@ -351,6 +351,11 @@ library DeployUtils {
}
}
/// @notice The unstructured storage slot that is used for v5 openzeppelin initializable. Computed as:
/// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) &
/// ~bytes32(uint256(0xff))
bytes32 internal constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/// @notice Asserts that for a given contract the value of a storage slot at an offset is 1 or
/// `type(uint8).max`. The value is set to 1 when a contract is initialized, and set to
/// `type(uint8).max` when `_disableInitializers` is called.
......@@ -362,4 +367,9 @@ library DeployUtils {
"DeployUtils: value at the given slot and offset does not indicate initialization"
);
}
/// @notice Asserts that the contract has been initialized, assuming that it is using openzeppelin v5 initializable.
function assertInitialized(address _contractAddress) internal view {
assertInitialized({ _contractAddress: _contractAddress, _slot: uint256(INITIALIZABLE_STORAGE), _offset: 0 });
}
}
......@@ -5,6 +5,7 @@ import { Vm } from "forge-std/Vm.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { LibString } from "@solady/utils/LibString.sol";
import { Executables } from "scripts/libraries/Executables.sol";
import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
import { Process } from "scripts/libraries/Process.sol";
/// @notice Contains information about a storage slot. Mirrors the layout of the storage
......@@ -190,6 +191,19 @@ library ForgeArtifacts {
function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) {
string memory storageLayout = getStorageLayout(_contractName);
// Contracts that use oz v5 should be here
if (LibString.eq(_contractName, "L1ERC721Bridge")) {
StorageSlot memory slot = StorageSlot({
astId: 0,
_contract: _contractName,
label: "_initialized",
offset: 0,
slot: vm.toString(DeployUtils.INITIALIZABLE_STORAGE),
_type: "bool"
});
return slot;
}
// FaultDisputeGame and PermissionedDisputeGame use a different name for the initialized storage slot.
string memory slotName = "_initialized";
string memory slotType = "t_uint8";
......@@ -214,7 +228,10 @@ library ForgeArtifacts {
slotType,
"\")'"
);
bytes memory rawSlot = vm.parseJson(string(Process.run(command)));
bytes memory result = Process.run(command);
require(result.length > 0, string.concat("ForgeArtifacts: ", _contractName, "is not initializable"));
bytes memory rawSlot = vm.parseJson(string(result));
slot_ = abi.decode(rawSlot, (StorageSlot));
}
......
This diff is collapsed.
[
{
"inputs": [
{
"internalType": "address",
"name": "_recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "_minWithdrawalAmount",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "_withdrawalNetwork",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"stateMutability": "payable",
"type": "receive"
......@@ -56,7 +35,30 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "config",
"outputs": [
{
"internalType": "address",
"name": "recipient_",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount_",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......@@ -128,7 +130,7 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "network_",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......
......@@ -121,6 +121,25 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
}
],
"name": "getConfig",
"outputs": [
{
"internalType": "bytes",
"name": "data_",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hash",
......@@ -147,6 +166,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isIsthmus",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1FeeOverhead",
......@@ -199,6 +231,24 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
{
"internalType": "bytes",
"name": "_value",
"type": "bytes"
}
],
"name": "setConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -227,6 +277,13 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setIsthmus",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -343,5 +400,10 @@
"inputs": [],
"name": "NotDepositor",
"type": "error"
},
{
"inputs": [],
"name": "UnsafeCast",
"type": "error"
}
]
\ No newline at end of file
......@@ -141,6 +141,25 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
}
],
"name": "getConfig",
"outputs": [
{
"internalType": "bytes",
"name": "data_",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hash",
......@@ -199,6 +218,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isIsthmus",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1FeeOverhead",
......@@ -254,7 +286,7 @@
{
"inputs": [
{
"internalType": "enum ConfigType",
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
......@@ -297,6 +329,13 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "setIsthmus",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -471,5 +510,10 @@
"inputs": [],
"name": "NotDepositor",
"type": "error"
},
{
"inputs": [],
"name": "UnsafeCast",
"type": "error"
}
]
\ No newline at end of file
......@@ -223,7 +223,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......
......@@ -209,7 +209,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -342,12 +342,22 @@
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"internalType": "uint64",
"name": "version",
"type": "uint8"
"type": "uint64"
}
],
"name": "Initialized",
"type": "event"
},
{
"inputs": [],
"name": "InvalidInitialization",
"type": "error"
},
{
"inputs": [],
"name": "NotInitializing",
"type": "error"
}
]
\ No newline at end of file
[
{
"inputs": [
{
"internalType": "address",
"name": "_recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "_minWithdrawalAmount",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "_withdrawalNetwork",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"stateMutability": "payable",
"type": "receive"
......@@ -56,7 +35,30 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "config",
"outputs": [
{
"internalType": "address",
"name": "recipient_",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount_",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......@@ -128,7 +130,7 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "network_",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......
......@@ -26,7 +26,7 @@
"name": "OTHER_BRIDGE",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
......@@ -447,7 +447,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -468,12 +468,12 @@
"name": "otherBridge",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "MESSAGE_VERSION",
......@@ -164,19 +159,6 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract CrossDomainMessenger",
"name": "_l1CrossDomainMessenger",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "l1CrossDomainMessenger",
......@@ -348,19 +330,6 @@
"name": "FailedRelayedMessage",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
......
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "MESSENGER",
......@@ -139,19 +134,6 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_l1ERC721Bridge",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "messenger",
......@@ -162,7 +144,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -289,18 +271,5 @@
],
"name": "ERC721BridgeInitiated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
}
]
\ No newline at end of file
[
{
"inputs": [],
"name": "BRIDGE",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "bridge",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_remoteToken",
"type": "address"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_symbol",
"type": "string"
}
],
"name": "createOptimismMintableERC20",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_remoteToken",
"type": "address"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_symbol",
"type": "string"
},
{
"internalType": "uint8",
"name": "_decimals",
"type": "uint8"
}
],
"name": "createOptimismMintableERC20WithDecimals",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_remoteToken",
"type": "address"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_symbol",
"type": "string"
}
],
"name": "createStandardL2Token",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "deployments",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "localToken",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "remoteToken",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "deployer",
"type": "address"
}
],
"name": "OptimismMintableERC20Created",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "remoteToken",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "localToken",
"type": "address"
}
],
"name": "StandardL2TokenCreated",
"type": "event"
}
]
\ No newline at end of file
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "addressManager",
"outputs": [
{
"internalType": "contract IAddressManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_proxy",
"type": "address"
},
{
"internalType": "address",
"name": "_newAdmin",
"type": "address"
}
],
"name": "changeProxyAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_proxy",
"type": "address"
}
],
"name": "getProxyAdmin",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_proxy",
"type": "address"
}
],
"name": "getProxyImplementation",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "implementationName",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isUpgrading",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "proxyType",
"outputs": [
{
"internalType": "enum ProxyAdmin.ProxyType",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "address",
"name": "_address",
"type": "address"
}
],
"name": "setAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IAddressManager",
"name": "_address",
"type": "address"
}
],
"name": "setAddressManager",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_address",
"type": "address"
},
{
"internalType": "string",
"name": "_name",
"type": "string"
}
],
"name": "setImplementationName",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_address",
"type": "address"
},
{
"internalType": "enum ProxyAdmin.ProxyType",
"name": "_type",
"type": "uint8"
}
],
"name": "setProxyType",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_upgrading",
"type": "bool"
}
],
"name": "setUpgrading",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_proxy",
"type": "address"
},
{
"internalType": "address",
"name": "_implementation",
"type": "address"
}
],
"name": "upgrade",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_proxy",
"type": "address"
},
{
"internalType": "address",
"name": "_implementation",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"name": "upgradeAndCall",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
}
]
\ No newline at end of file
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"stateMutability": "payable",
"type": "receive"
......@@ -26,7 +21,7 @@
"name": "OTHER_BRIDGE",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
......@@ -236,19 +231,6 @@
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract StandardBridge",
"name": "_otherBridge",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "l1TokenBridge",
......@@ -272,7 +254,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -280,7 +262,7 @@
"name": "otherBridge",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
......@@ -566,19 +548,6 @@
"name": "ETHBridgeInitiated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
......
......@@ -21,7 +21,7 @@
"name": "OTHER_BRIDGE",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
......@@ -254,19 +254,6 @@
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract StandardBridge",
"name": "_otherBridge",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "l1TokenBridge",
......@@ -290,7 +277,7 @@
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -298,7 +285,7 @@
"name": "otherBridge",
"outputs": [
{
"internalType": "contract StandardBridge",
"internalType": "contract IStandardBridge",
"name": "",
"type": "address"
}
......@@ -615,19 +602,6 @@
"name": "ETHBridgeInitiated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
......
......@@ -137,6 +137,11 @@
"internalType": "address",
"name": "challenger",
"type": "address"
},
{
"internalType": "address",
"name": "systemConfigFeeAdmin",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Roles",
......
......@@ -137,6 +137,11 @@
"internalType": "address",
"name": "challenger",
"type": "address"
},
{
"internalType": "address",
"name": "systemConfigFeeAdmin",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Roles",
......
......@@ -2,7 +2,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IL2ERC721Bridge",
"name": "_bridge",
"type": "address"
},
......@@ -35,7 +35,7 @@
"name": "BRIDGE",
"outputs": [
{
"internalType": "address",
"internalType": "contract IL2ERC721Bridge",
"name": "",
"type": "address"
}
......@@ -124,7 +124,7 @@
"name": "bridge",
"outputs": [
{
"internalType": "address",
"internalType": "contract IL2ERC721Bridge",
"name": "",
"type": "address"
}
......
[
{
"inputs": [
{
"internalType": "address",
"name": "_bridge",
"type": "address"
},
{
"internalType": "uint256",
"name": "_remoteChainId",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "BRIDGE",
"outputs": [
{
"internalType": "address",
"internalType": "contract IL2ERC721Bridge",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -46,12 +30,12 @@
"name": "bridge",
"outputs": [
{
"internalType": "address",
"internalType": "contract IL2ERC721Bridge",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"stateMutability": "pure",
"type": "function"
},
{
......@@ -104,7 +88,7 @@
},
{
"inputs": [],
"name": "remoteChainID",
"name": "remoteChainId",
"outputs": [
{
"internalType": "uint256",
......
......@@ -413,27 +413,17 @@
{
"inputs": [
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint8",
"name": "_decimals",
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "_name",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "_symbol",
"type": "bytes32"
"internalType": "bytes",
"name": "_value",
"type": "bytes"
}
],
"name": "setGasPayingToken",
"name": "setConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
......
......@@ -605,27 +605,17 @@
{
"inputs": [
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint8",
"name": "_decimals",
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "_name",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "_symbol",
"type": "bytes32"
"internalType": "bytes",
"name": "_value",
"type": "bytes"
}
],
"name": "setGasPayingToken",
"name": "setConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
......@@ -669,6 +659,24 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_gasLimit",
"type": "uint32"
},
{
"internalType": "bytes",
"name": "_calldata",
"type": "bytes"
}
],
"name": "upgrade",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "version",
......
......@@ -605,7 +605,7 @@
{
"inputs": [
{
"internalType": "enum ConfigType",
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
......@@ -620,34 +620,6 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint8",
"name": "_decimals",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "_name",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "_symbol",
"type": "bytes32"
}
],
"name": "setGasPayingToken",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -687,6 +659,24 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_gasLimit",
"type": "uint32"
},
{
"internalType": "bytes",
"name": "_calldata",
"type": "bytes"
}
],
"name": "upgrade",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "version",
......
[
{
"inputs": [
{
"internalType": "address",
"name": "_recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "_minWithdrawalAmount",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "_withdrawalNetwork",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"stateMutability": "payable",
"type": "receive"
......@@ -56,7 +35,30 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "config",
"outputs": [
{
"internalType": "address",
"name": "recipient_",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount_",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......@@ -69,7 +71,7 @@
"outputs": [
{
"internalType": "address",
"name": "",
"name": "recipient_",
"type": "address"
}
],
......@@ -141,7 +143,7 @@
"outputs": [
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "network_",
"name": "withdrawalNetwork_",
"type": "uint8"
}
],
......
......@@ -30,6 +30,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "UPGRADER_SLOT",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "guardian",
......@@ -50,6 +63,11 @@
"name": "_guardian",
"type": "address"
},
{
"internalType": "address",
"name": "_upgrader",
"type": "address"
},
{
"internalType": "bool",
"name": "_paused",
......@@ -94,6 +112,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "upgrader",
"outputs": [
{
"internalType": "address",
"name": "upgrader_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
......
......@@ -225,6 +225,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "feeAdmin",
"outputs": [
{
"internalType": "address",
"name": "addr_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gasLimit",
......@@ -284,11 +297,33 @@
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "_owner",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "feeAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "unsafeBlockSigner",
"type": "address"
},
{
"internalType": "bytes32",
"name": "batcherHash",
"type": "bytes32"
}
],
"internalType": "struct SystemConfig.Roles",
"name": "_roles",
"type": "tuple"
},
{
"internalType": "uint32",
"name": "_basefeeScalar",
......@@ -299,21 +334,11 @@
"name": "_blobbasefeeScalar",
"type": "uint32"
},
{
"internalType": "bytes32",
"name": "_batcherHash",
"type": "bytes32"
},
{
"internalType": "uint64",
"name": "_gasLimit",
"type": "uint64"
},
{
"internalType": "address",
"name": "_unsafeBlockSigner",
"type": "address"
},
{
"components": [
{
......@@ -630,6 +655,34 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "_min",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "_network",
"type": "uint8"
}
],
"name": "setFeeVaultConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -800,5 +853,10 @@
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [],
"name": "UnsafeCast",
"type": "error"
}
]
\ No newline at end of file
......@@ -246,6 +246,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "feeAdmin",
"outputs": [
{
"internalType": "address",
"name": "addr_",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gasLimit",
......@@ -305,11 +318,33 @@
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "_owner",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "feeAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "unsafeBlockSigner",
"type": "address"
},
{
"internalType": "bytes32",
"name": "batcherHash",
"type": "bytes32"
}
],
"internalType": "struct SystemConfig.Roles",
"name": "_roles",
"type": "tuple"
},
{
"internalType": "uint32",
"name": "_basefeeScalar",
......@@ -320,21 +355,11 @@
"name": "_blobbasefeeScalar",
"type": "uint32"
},
{
"internalType": "bytes32",
"name": "_batcherHash",
"type": "bytes32"
},
{
"internalType": "uint64",
"name": "_gasLimit",
"type": "uint64"
},
{
"internalType": "address",
"name": "_unsafeBlockSigner",
"type": "address"
},
{
"components": [
{
......@@ -418,11 +443,6 @@
"internalType": "struct SystemConfig.Addresses",
"name": "_addresses",
"type": "tuple"
},
{
"internalType": "address",
"name": "_dependencyManager",
"type": "address"
}
],
"name": "initialize",
......@@ -432,11 +452,33 @@
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "_owner",
"name": "feeAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "unsafeBlockSigner",
"type": "address"
},
{
"internalType": "bytes32",
"name": "batcherHash",
"type": "bytes32"
}
],
"internalType": "struct SystemConfig.Roles",
"name": "_roles",
"type": "tuple"
},
{
"internalType": "uint32",
"name": "_basefeeScalar",
......@@ -447,21 +489,11 @@
"name": "_blobbasefeeScalar",
"type": "uint32"
},
{
"internalType": "bytes32",
"name": "_batcherHash",
"type": "bytes32"
},
{
"internalType": "uint64",
"name": "_gasLimit",
"type": "uint64"
},
{
"internalType": "address",
"name": "_unsafeBlockSigner",
"type": "address"
},
{
"components": [
{
......@@ -545,6 +577,11 @@
"internalType": "struct SystemConfig.Addresses",
"name": "_addresses",
"type": "tuple"
},
{
"internalType": "address",
"name": "_dependencyManager",
"type": "address"
}
],
"name": "initialize",
......@@ -791,6 +828,34 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "enum Types.ConfigType",
"name": "_type",
"type": "uint8"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "_min",
"type": "uint256"
},
{
"internalType": "enum Types.WithdrawalNetwork",
"name": "_network",
"type": "uint8"
}
],
"name": "setFeeVaultConfig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
......@@ -961,5 +1026,10 @@
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [],
"name": "UnsafeCast",
"type": "error"
}
]
\ No newline at end of file
[
{
"bytes": "20",
"label": "spacer_0_0_20",
"offset": 0,
"slot": "0",
"type": "address"
}
]
\ No newline at end of file
[
{
"bytes": "1600",
"label": "spacer_1_0_1600",
"offset": 0,
"slot": "0",
"type": "uint256[50]"
},
{
"bytes": "20",
"label": "spacer_51_0_20",
"offset": 0,
"slot": "50",
"type": "address"
},
{
"bytes": "1568",
"label": "spacer_52_0_1568",
"offset": 0,
"slot": "51",
"type": "uint256[49]"
},
{
"bytes": "1",
"label": "spacer_101_0_1",
"offset": 0,
"slot": "100",
"type": "bool"
},
{
"bytes": "1568",
"label": "spacer_102_0_1568",
"offset": 0,
"slot": "101",
"type": "uint256[49]"
},
{
"bytes": "32",
"label": "spacer_151_0_32",
"offset": 0,
"slot": "150",
"type": "uint256"
},
{
"bytes": "1568",
"label": "spacer_152_0_1568",
"offset": 0,
"slot": "151",
"type": "uint256[49]"
},
{
"bytes": "32",
"label": "spacer_201_0_32",
"offset": 0,
"slot": "200",
"type": "mapping(bytes32 => bool)"
},
{
"bytes": "32",
"label": "spacer_202_0_32",
"offset": 0,
"slot": "201",
"type": "mapping(bytes32 => bool)"
}
]
\ No newline at end of file
......@@ -75,5 +75,12 @@
"offset": 0,
"slot": "7",
"type": "uint256"
},
{
"bytes": "1",
"label": "isIsthmus",
"offset": 0,
"slot": "8",
"type": "bool"
}
]
\ No newline at end of file
......@@ -76,11 +76,18 @@
"slot": "7",
"type": "uint256"
},
{
"bytes": "1",
"label": "isIsthmus",
"offset": 0,
"slot": "8",
"type": "bool"
},
{
"bytes": "64",
"label": "dependencySet",
"offset": 0,
"slot": "8",
"slot": "9",
"type": "struct EnumerableSet.UintSet"
}
]
\ No newline at end of file
......@@ -7,18 +7,11 @@
"type": "address"
},
{
"bytes": "1",
"label": "_initialized",
"bytes": "12",
"label": "spacer_0_20_12",
"offset": 20,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 21,
"slot": "0",
"type": "bool"
"type": "bytes12"
},
{
"bytes": "1600",
......@@ -92,10 +85,10 @@
},
{
"bytes": "20",
"label": "xDomainMsgSender",
"label": "spacer_204_0_20",
"offset": 0,
"slot": "204",
"type": "address"
"type": "bytes20"
},
{
"bytes": "30",
......@@ -113,17 +106,52 @@
},
{
"bytes": "20",
"label": "otherMessenger",
"label": "spacer_207_0_20",
"offset": 0,
"slot": "207",
"type": "contract CrossDomainMessenger"
"type": "address"
},
{
"bytes": "1376",
"label": "__gap",
"bytes": "20",
"label": "xDomainMsgSender",
"offset": 0,
"slot": "208",
"type": "uint256[43]"
"type": "address"
},
{
"bytes": "12",
"label": "spacer_208_20_12",
"offset": 20,
"slot": "208",
"type": "bytes12"
},
{
"bytes": "1312",
"label": "__gap",
"offset": 0,
"slot": "209",
"type": "uint256[41]"
},
{
"bytes": "1",
"label": "_initialized",
"offset": 0,
"slot": "250",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "250",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_250_2_30",
"offset": 2,
"slot": "250",
"type": "bytes30"
},
{
"bytes": "20",
......
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
"type": "bytes32"
},
{
"bytes": "20",
"label": "messenger",
"label": "spacer_1_0_20",
"offset": 0,
"slot": "1",
"type": "contract ICrossDomainMessenger"
"type": "address"
},
{
"bytes": "20",
"label": "otherBridge",
"label": "spacer_2_0_20",
"offset": 0,
"slot": "2",
"type": "contract ERC721Bridge"
"type": "address"
},
{
"bytes": "1472",
......@@ -54,5 +40,12 @@
"offset": 0,
"slot": "50",
"type": "contract ISuperchainConfig"
},
{
"bytes": "20",
"label": "crossDomainMessenger",
"offset": 0,
"slot": "51",
"type": "contract ICrossDomainMessenger"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
"type": "bytes32"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
},
{
"bytes": "20",
"label": "bridge",
"bytes": "32",
"label": "spacer_1_0_32",
"offset": 0,
"slot": "1",
"type": "address"
"type": "bytes32"
},
{
"bytes": "32",
......@@ -40,5 +26,33 @@
"offset": 0,
"slot": "3",
"type": "uint256[48]"
},
{
"bytes": "1",
"label": "_initialized",
"offset": 0,
"slot": "51",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "51",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_51_2_30",
"offset": 2,
"slot": "51",
"type": "bytes30"
},
{
"bytes": "20",
"label": "standardBridge",
"offset": 0,
"slot": "52",
"type": "address"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
"type": "bytes32"
},
{
"bytes": "20",
......@@ -36,24 +22,45 @@
},
{
"bytes": "20",
"label": "messenger",
"label": "spacer_3_0_20",
"offset": 0,
"slot": "3",
"type": "contract ICrossDomainMessenger"
"type": "address"
},
{
"bytes": "20",
"label": "otherBridge",
"label": "spacer_4_0_20",
"offset": 0,
"slot": "4",
"type": "contract StandardBridge"
"type": "address"
},
{
"bytes": "1440",
"bytes": "1408",
"label": "__gap",
"offset": 0,
"slot": "5",
"type": "uint256[45]"
"type": "uint256[44]"
},
{
"bytes": "1",
"label": "_initialized",
"offset": 0,
"slot": "49",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "49",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_49_2_30",
"offset": 2,
"slot": "49",
"type": "bytes30"
},
{
"bytes": "20",
......@@ -68,5 +75,12 @@
"offset": 0,
"slot": "51",
"type": "contract ISystemConfig"
},
{
"bytes": "20",
"label": "crossDomainMessenger",
"offset": 0,
"slot": "52",
"type": "contract ICrossDomainMessenger"
}
]
\ No newline at end of file
......@@ -7,18 +7,11 @@
"type": "address"
},
{
"bytes": "1",
"label": "_initialized",
"bytes": "12",
"label": "spacer_0_20_12",
"offset": 20,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 21,
"slot": "0",
"type": "bool"
"type": "bytes12"
},
{
"bytes": "1600",
......@@ -92,10 +85,10 @@
},
{
"bytes": "20",
"label": "xDomainMsgSender",
"label": "spacer_204_0_20",
"offset": 0,
"slot": "204",
"type": "address"
"type": "bytes20"
},
{
"bytes": "30",
......@@ -113,16 +106,30 @@
},
{
"bytes": "20",
"label": "otherMessenger",
"label": "spacer_207_0_20",
"offset": 0,
"slot": "207",
"type": "contract CrossDomainMessenger"
"type": "address"
},
{
"bytes": "1376",
"label": "__gap",
"bytes": "20",
"label": "xDomainMsgSender",
"offset": 0,
"slot": "208",
"type": "uint256[43]"
"type": "address"
},
{
"bytes": "12",
"label": "spacer_208_20_12",
"offset": 20,
"slot": "208",
"type": "bytes12"
},
{
"bytes": "1312",
"label": "__gap",
"offset": 0,
"slot": "209",
"type": "uint256[41]"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
"type": "bytes32"
},
{
"bytes": "20",
"label": "messenger",
"label": "spacer_1_0_20",
"offset": 0,
"slot": "1",
"type": "contract ICrossDomainMessenger"
"type": "address"
},
{
"bytes": "20",
"label": "otherBridge",
"label": "spacer_2_0_20",
"offset": 0,
"slot": "2",
"type": "contract ERC721Bridge"
"type": "address"
},
{
"bytes": "1472",
......
[
{
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "bytes32"
},
{
"bytes": "32",
"label": "spacer_1_0_32",
"offset": 0,
"slot": "1",
"type": "bytes32"
},
{
"bytes": "32",
"label": "deployments",
"offset": 0,
"slot": "2",
"type": "mapping(address => address)"
},
{
"bytes": "1536",
"label": "__gap",
"offset": 0,
"slot": "3",
"type": "uint256[48]"
}
]
\ No newline at end of file
[
{
"bytes": "20",
"label": "_owner",
"offset": 0,
"slot": "0",
"type": "address"
},
{
"bytes": "32",
"label": "proxyType",
"offset": 0,
"slot": "1",
"type": "mapping(address => enum ProxyAdmin.ProxyType)"
},
{
"bytes": "32",
"label": "implementationName",
"offset": 0,
"slot": "2",
"type": "mapping(address => string)"
},
{
"bytes": "20",
"label": "addressManager",
"offset": 0,
"slot": "3",
"type": "contract IAddressManager"
},
{
"bytes": "1",
"label": "upgrading",
"offset": 20,
"slot": "3",
"type": "bool"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
"type": "bytes32"
},
{
"bytes": "20",
......@@ -36,23 +22,23 @@
},
{
"bytes": "20",
"label": "messenger",
"label": "spacer_3_0_20",
"offset": 0,
"slot": "3",
"type": "contract ICrossDomainMessenger"
"type": "address"
},
{
"bytes": "20",
"label": "otherBridge",
"label": "spacer_4_0_20",
"offset": 0,
"slot": "4",
"type": "contract StandardBridge"
"type": "address"
},
{
"bytes": "1440",
"bytes": "1408",
"label": "__gap",
"offset": 0,
"slot": "5",
"type": "uint256[45]"
"type": "uint256[44]"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"bytes": "32",
"label": "spacer_0_0_32",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "30",
"label": "spacer_0_2_30",
"offset": 2,
"slot": "0",
"type": "bytes30"
"type": "bytes32"
},
{
"bytes": "20",
......@@ -36,23 +22,23 @@
},
{
"bytes": "20",
"label": "messenger",
"label": "spacer_3_0_20",
"offset": 0,
"slot": "3",
"type": "contract ICrossDomainMessenger"
"type": "address"
},
{
"bytes": "20",
"label": "otherBridge",
"label": "spacer_4_0_20",
"offset": 0,
"slot": "4",
"type": "contract StandardBridge"
"type": "address"
},
{
"bytes": "1440",
"bytes": "1408",
"label": "__gap",
"offset": 0,
"slot": "5",
"type": "uint256[45]"
"type": "uint256[44]"
}
]
\ No newline at end of file
......@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
// Contracts
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
......@@ -18,7 +19,10 @@ import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol";
/// @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible
/// for sending and receiving data on the L1 side. Users are encouraged to use this
/// interface instead of interacting with lower-level contracts directly.
contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver, Initializable {
/// @notice Spacer to give the initializer a full slot, to avoid offsetting the superchainConfig slot.
bytes30 private spacer_250_2_30;
/// @notice Contract of the SuperchainConfig.
ISuperchainConfig public superchainConfig;
......@@ -30,16 +34,12 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
ISystemConfig public systemConfig;
/// @notice Semantic version.
/// @custom:semver 2.4.1-beta.2
string public constant version = "2.4.1-beta.2";
/// @custom:semver 2.4.1-beta.3
string public constant version = "2.4.1-beta.3";
/// @notice Constructs the L1CrossDomainMessenger contract.
constructor() CrossDomainMessenger() {
initialize({
_superchainConfig: ISuperchainConfig(address(0)),
_portal: IOptimismPortal(payable(address(0))),
_systemConfig: ISystemConfig(address(0))
});
_disableInitializers();
}
/// @notice Initializes the contract.
......@@ -57,7 +57,12 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
superchainConfig = _superchainConfig;
portal = _portal;
systemConfig = _systemConfig;
__CrossDomainMessenger_init({ _otherMessenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER) });
}
/// @notice Getter function for the other messenger.
/// @return Contract of the messenger on the other network.
function otherMessenger() public pure override returns (CrossDomainMessenger) {
return CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);
}
/// @inheritdoc CrossDomainMessenger
......@@ -86,7 +91,7 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
/// @inheritdoc CrossDomainMessenger
function _isOtherMessenger() internal view override returns (bool) {
return msg.sender == address(portal) && portal.l2Sender() == address(otherMessenger);
return msg.sender == address(portal) && portal.l2Sender() == address(otherMessenger());
}
/// @inheritdoc CrossDomainMessenger
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
pragma solidity 0.8.25;
// Contracts
import { ERC721Bridge } from "src/universal/ERC721Bridge.sol";
import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
......@@ -19,7 +20,7 @@ import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol";
/// @notice The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to
/// make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract
/// acts as an escrow for ERC721 tokens deposited into L2.
contract L1ERC721Bridge is ERC721Bridge, ISemver {
contract L1ERC721Bridge is ERC721Bridge, Initializable, ISemver {
/// @notice Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token
/// by ID was deposited for a given L2 token.
mapping(address => mapping(address => mapping(uint256 => bool))) public deposits;
......@@ -27,13 +28,16 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver {
/// @notice Address of the SuperchainConfig contract.
ISuperchainConfig public superchainConfig;
/// @notice Contract of the CrossDomainMessenger on this chain.
ICrossDomainMessenger internal crossDomainMessenger;
/// @notice Semantic version.
/// @custom:semver 2.2.0-beta.1
string public constant version = "2.2.0-beta.1";
/// @custom:semver 2.1.1-beta.3
string public constant version = "2.1.1-beta.3";
/// @notice Constructs the L1ERC721Bridge contract.
constructor() ERC721Bridge() {
initialize({ _messenger: ICrossDomainMessenger(address(0)), _superchainConfig: ISuperchainConfig(address(0)) });
_disableInitializers();
}
/// @notice Initializes the contract.
......@@ -41,7 +45,19 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver {
/// @param _superchainConfig Contract of the SuperchainConfig contract on this network.
function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) public initializer {
superchainConfig = _superchainConfig;
__ERC721Bridge_init({ _messenger: _messenger, _otherBridge: ERC721Bridge(payable(Predeploys.L2_ERC721_BRIDGE)) });
crossDomainMessenger = _messenger;
}
/// @notice Getter function for the CrossDomainMessenger contract on this chain.
/// @return Contract of the CrossDomainMessenger on this chain.
function messenger() public view override returns (ICrossDomainMessenger) {
return ICrossDomainMessenger(crossDomainMessenger);
}
/// @notice Getter function for the other bridge.
/// @return Contract of the bridge on the other network.
function otherBridge() public pure override returns (ERC721Bridge) {
return ERC721Bridge(payable(Predeploys.L2_ERC721_BRIDGE));
}
/// @inheritdoc ERC721Bridge
......@@ -116,7 +132,7 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver {
IERC721(_localToken).transferFrom({ from: _from, to: address(this), tokenId: _tokenId });
// Send calldata into L2
messenger.sendMessage({ _target: address(otherBridge), _message: message, _minGasLimit: _minGasLimit });
messenger().sendMessage({ _target: address(otherBridge()), _message: message, _minGasLimit: _minGasLimit });
emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
/// @custom:proxied true
/// @title L1OptimismMintableERC20Factory
/// @notice Allows users to create L1 tokens that represent L2 native tokens.
contract L1OptimismMintableERC20Factory is OptimismMintableERC20Factory, Initializable {
/// @custom:semver 1.3.1-beta.5
/// @notice Semantic version.
/// The semver MUST be bumped any time that there is a change in
/// the OptimismMintableERC20 token contract since this contract
/// is responsible for deploying OptimismMintableERC20 contracts.
string public constant version = "1.3.1-beta.5";
/// @custom:spacer
/// @notice Spacer to fill the remainder of the _initialized slot, preventing the standardBridge
/// address from being packed with it.
bytes30 private spacer_51_2_30;
/// @notice Address of the bridge on this domain.
address internal standardBridge;
constructor() {
_disableInitializers();
}
/// @notice Initializes the contract.
/// @param _bridge Contract of the bridge on this domain.
function initialize(address _bridge) public initializer {
standardBridge = _bridge;
}
/// @notice Getter function for the bridge contract.
/// @return Contract of the bridge on this domain.
function bridge() public view virtual override returns (address) {
return standardBridge;
}
}
......@@ -3,15 +3,16 @@ pragma solidity 0.8.15;
// Contracts
import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
// Interfaces
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
/// @custom:proxied true
/// @title L1StandardBridge
......@@ -23,7 +24,7 @@ import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
/// NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples
/// of some token types that may not be properly supported by this contract include, but are
/// not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.
contract L1StandardBridge is StandardBridge, ISemver {
contract L1StandardBridge is StandardBridge, ISemver, Initializable {
/// @custom:legacy
/// @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.
/// @param from Address of the depositor.
......@@ -75,8 +76,13 @@ contract L1StandardBridge is StandardBridge, ISemver {
);
/// @notice Semantic version.
/// @custom:semver 2.2.1-beta.2
string public constant version = "2.2.1-beta.2";
/// @custom:semver 2.2.1-beta.3
string public constant version = "2.2.1-beta.3";
/// @custom:spacer
/// @notice Spacer to fill the remainder of the _initialized slot, preventing the superchainConfig
/// address from being packed with it.
bytes30 private spacer_49_2_30;
/// @notice Address of the SuperchainConfig contract.
ISuperchainConfig public superchainConfig;
......@@ -84,13 +90,12 @@ contract L1StandardBridge is StandardBridge, ISemver {
/// @notice Address of the SystemConfig contract.
ISystemConfig public systemConfig;
/// @notice Contract for the CrossDomainMessenger on this network.
ICrossDomainMessenger internal crossDomainMessenger;
/// @notice Constructs the L1StandardBridge contract.
constructor() StandardBridge() {
initialize({
_messenger: ICrossDomainMessenger(address(0)),
_superchainConfig: ISuperchainConfig(address(0)),
_systemConfig: ISystemConfig(address(0))
});
_disableInitializers();
}
/// @notice Initializer.
......@@ -106,10 +111,19 @@ contract L1StandardBridge is StandardBridge, ISemver {
{
superchainConfig = _superchainConfig;
systemConfig = _systemConfig;
__StandardBridge_init({
_messenger: _messenger,
_otherBridge: StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE))
});
crossDomainMessenger = _messenger;
}
/// @notice Returns the contract of the bridge on the other chain.
/// @return Contract of the bridge on the other chain.
function otherBridge() public pure override returns (IStandardBridge) {
return IStandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
}
/// @notice Getter function for the messenger contract.
/// @return Contract of the messenger on this domain.
function messenger() public view override returns (ICrossDomainMessenger) {
return ICrossDomainMessenger(crossDomainMessenger);
}
/// @inheritdoc StandardBridge
......@@ -241,8 +255,8 @@ contract L1StandardBridge is StandardBridge, ISemver {
/// @custom:legacy
/// @notice Retrieves the access of the corresponding L2 bridge contract.
/// @return Address of the corresponding L2 bridge contract.
function l2TokenBridge() external view returns (address) {
return address(otherBridge);
function l2TokenBridge() external pure returns (address) {
return address(otherBridge());
}
/// @notice Internal function for initiating an ETH deposit.
......
......@@ -46,6 +46,7 @@ contract OPContractsManager is ISemver, Initializable {
address unsafeBlockSigner;
address proposer;
address challenger;
address systemConfigFeeAdmin;
}
/// @notice The full set of inputs to deploy a new OP Stack chain.
......@@ -129,8 +130,8 @@ contract OPContractsManager is ISemver, Initializable {
// -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.20
string public constant version = "1.0.0-beta.20";
/// @custom:semver 1.0.0-beta.21
string public constant version = "1.0.0-beta.21";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct
/// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
......@@ -254,7 +255,7 @@ contract OPContractsManager is ISemver, Initializable {
output.systemConfigProxy =
ISystemConfig(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "SystemConfig"));
output.optimismMintableERC20FactoryProxy = IOptimismMintableERC20Factory(
deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "OptimismMintableERC20Factory")
deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "L1OptimismMintableERC20Factory")
);
output.disputeGameFactoryProxy =
IDisputeGameFactory(deployProxy(l2ChainId, output.opChainProxyAdmin, saltMixer, "DisputeGameFactory"));
......@@ -468,12 +469,15 @@ contract OPContractsManager is ISemver, Initializable {
return abi.encodeWithSelector(
_selector,
_input.roles.systemConfigOwner,
ISystemConfig.Roles({
owner: _input.roles.systemConfigOwner,
feeAdmin: _input.roles.systemConfigFeeAdmin,
unsafeBlockSigner: _input.roles.unsafeBlockSigner,
batcherHash: bytes32(uint256(uint160(_input.roles.batcher)))
}),
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs
......@@ -487,12 +491,15 @@ contract OPContractsManager is ISemver, Initializable {
return abi.encodeWithSelector(
_selector,
_input.roles.systemConfigOwner,
ISystemConfig.Roles({
owner: _input.roles.systemConfigOwner,
feeAdmin: _input.roles.systemConfigFeeAdmin,
unsafeBlockSigner: _input.roles.unsafeBlockSigner,
batcherHash: bytes32(uint256(uint160(_input.roles.batcher)))
}),
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs
......
......@@ -41,12 +41,15 @@ contract OPContractsManagerInterop is OPContractsManager {
return abi.encodeWithSelector(
_selector,
_input.roles.systemConfigOwner,
ISystemConfig.Roles({
owner: _input.roles.systemConfigOwner,
feeAdmin: _input.roles.systemConfigFeeAdmin,
unsafeBlockSigner: _input.roles.unsafeBlockSigner,
batcherHash: bytes32(uint256(uint160(_input.roles.batcher)))
}),
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs,
......
......@@ -146,9 +146,9 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
}
/// @notice Semantic version.
/// @custom:semver 2.8.1-beta.4
/// @custom:semver 2.8.1-beta.5
function version() public pure virtual returns (string memory) {
return "2.8.1-beta.4";
return "2.8.1-beta.5";
}
/// @notice Constructs the OptimismPortal contract.
......@@ -584,17 +584,17 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}
/// @notice Sets the gas paying token for the L2 system. This token is used as the
/// L2 native asset. Only the SystemConfig contract can call this function.
function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external {
/// @notice Sets static configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(Types.ConfigType _type, bytes memory _value) external {
if (msg.sender != address(systemConfig)) revert Unauthorized();
// Set L2 deposit gas as used without paying burning gas. Ensures that deposits cannot use too much L2 gas.
// This value must be large enough to cover the cost of calling `L1Block.setGasPayingToken`.
// This value must be large enough to cover the cost of calling `L1Block.setConfig`.
useGas(SYSTEM_DEPOSIT_GAS_LIMIT);
// Emit the special deposit transaction directly that sets the gas paying
// token in the L1Block predeploy contract.
// Emit the special deposit transaction directly that sets the config in the L1Block predeploy contract.
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.L1_BLOCK_ATTRIBUTES,
......@@ -604,7 +604,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
uint256(0), // value
uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit
false, // isCreation,
abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol))
abi.encodeCall(IL1Block.setConfig, (_type, _value))
)
);
}
......
......@@ -183,9 +183,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
}
/// @notice Semantic version.
/// @custom:semver 3.11.0-beta.6
/// @custom:semver 3.11.0-beta.7
function version() public pure virtual returns (string memory) {
return "3.11.0-beta.6";
return "3.11.0-beta.7";
}
/// @notice Constructs the OptimismPortal contract.
......@@ -605,17 +605,17 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}
/// @notice Sets the gas paying token for the L2 system. This token is used as the
/// L2 native asset. Only the SystemConfig contract can call this function.
function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external {
/// @notice Sets static configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(Types.ConfigType _type, bytes memory _value) external {
if (msg.sender != address(systemConfig)) revert Unauthorized();
// Set L2 deposit gas as used without paying burning gas. Ensures that deposits cannot use too much L2 gas.
// This value must be large enough to cover the cost of calling `L1Block.setGasPayingToken`.
// This value must be large enough to cover the cost of calling `L1Block.setConfig`.
useGas(SYSTEM_DEPOSIT_GAS_LIMIT);
// Emit the special deposit transaction directly that sets the gas paying
// token in the L1Block predeploy contract.
// Emit the special deposit transaction directly that sets the config in the L1Block predeploy contract.
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.L1_BLOCK_ATTRIBUTES,
......@@ -625,7 +625,30 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
uint256(0), // value
uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit
false, // isCreation,
abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol))
abi.encodeCall(IL1Block.setConfig, (_type, _value))
)
);
}
/// @notice Calls the L2ProxyAdmin as the DEPOSITOR_ACCOUNT. This function can be used
/// to upgrade the predeploys on L2. Only callable by the upgrader role on the
/// SuperchainConfig.
function upgrade(uint32 _gasLimit, bytes memory _calldata) external {
if (msg.sender != superchainConfig.upgrader()) revert Unauthorized();
useGas(_gasLimit);
// Emit the special deposit transaction which calls to the L2 Proxy Admin
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.PROXY_ADMIN,
DEPOSIT_VERSION,
abi.encodePacked(
uint256(0), // mint
uint256(0), // value
uint64(_gasLimit), // gasLimit
false, // isCreation,
_calldata // data
)
);
}
......
......@@ -3,12 +3,6 @@ pragma solidity 0.8.15;
// Contracts
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Unauthorized } from "src/libraries/PortalErrors.sol";
/// @custom:proxied true
/// @title OptimismPortalInterop
......@@ -23,33 +17,8 @@ contract OptimismPortalInterop is OptimismPortal2 {
OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds)
{ }
/// @custom:semver +interop-beta.2
/// @custom:semver +interop-beta.3
function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop-beta.2");
}
/// @notice Sets static configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(ConfigType _type, bytes memory _value) external {
if (msg.sender != address(systemConfig)) revert Unauthorized();
// Set L2 deposit gas as used without paying burning gas. Ensures that deposits cannot use too much L2 gas.
// This value must be large enough to cover the cost of calling `L1Block.setConfig`.
useGas(SYSTEM_DEPOSIT_GAS_LIMIT);
// Emit the special deposit transaction directly that sets the config in the L1Block predeploy contract.
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.L1_BLOCK_ATTRIBUTES,
DEPOSIT_VERSION,
abi.encodePacked(
uint256(0), // mint
uint256(0), // value
uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit
false, // isCreation,
abi.encodeCall(L1BlockInterop.setConfig, (_type, _value))
)
);
return string.concat(super.version(), "+interop-beta.3");
}
}
......@@ -12,8 +12,10 @@ import { Storage } from "src/libraries/Storage.sol";
contract SuperchainConfig is Initializable, ISemver {
/// @notice Enum representing different types of updates.
/// @custom:value GUARDIAN Represents an update to the guardian.
/// @custom:value UPGRADER Represents an update to the upgrader.
enum UpdateType {
GUARDIAN
GUARDIAN,
UPGRADER
}
/// @notice Whether or not the Superchain is paused.
......@@ -23,6 +25,10 @@ contract SuperchainConfig is Initializable, ISemver {
/// It can only be modified by an upgrade.
bytes32 public constant GUARDIAN_SLOT = bytes32(uint256(keccak256("superchainConfig.guardian")) - 1);
/// @notice The address of the upgrader, which can faciliate upgrades of L2 predeploys.
/// . It can only be modified by an upgrade.
bytes32 public constant UPGRADER_SLOT = bytes32(uint256(keccak256("superchainConfig.upgrader")) - 1);
/// @notice Emitted when the pause is triggered.
/// @param identifier A string helping to identify provenance of the pause transaction.
event Paused(string identifier);
......@@ -36,19 +42,20 @@ contract SuperchainConfig is Initializable, ISemver {
event ConfigUpdate(UpdateType indexed updateType, bytes data);
/// @notice Semantic version.
/// @custom:semver 1.1.1-beta.1
string public constant version = "1.1.1-beta.1";
/// @custom:semver 1.1.1-beta.2
string public constant version = "1.1.1-beta.2";
/// @notice Constructs the SuperchainConfig contract.
constructor() {
initialize({ _guardian: address(0), _paused: false });
_disableInitializers();
}
/// @notice Initializer.
/// @param _guardian Address of the guardian, can pause the OptimismPortal.
/// @param _paused Initial paused status.
function initialize(address _guardian, bool _paused) public initializer {
function initialize(address _guardian, address _upgrader, bool _paused) public initializer {
_setGuardian(_guardian);
_setUpgrader(_upgrader);
if (_paused) {
_pause("Initializer paused");
}
......@@ -59,6 +66,11 @@ contract SuperchainConfig is Initializable, ISemver {
guardian_ = Storage.getAddress(GUARDIAN_SLOT);
}
/// @notice Getter for the upgrader address.
function upgrader() public view returns (address upgrader_) {
upgrader_ = Storage.getAddress(UPGRADER_SLOT);
}
/// @notice Getter for the current paused status.
function paused() public view returns (bool paused_) {
paused_ = Storage.getBool(PAUSED_SLOT);
......@@ -92,4 +104,12 @@ contract SuperchainConfig is Initializable, ISemver {
Storage.setAddress(GUARDIAN_SLOT, _guardian);
emit ConfigUpdate(UpdateType.GUARDIAN, abi.encode(_guardian));
}
/// @notice Sets the upgrader address. This is only callable during initialization, so an upgrade
/// will be required to change the upgrader.
/// @param _upgrader The new upgrader address.
function _setUpgrader(address _upgrader) internal {
Storage.setAddress(UPGRADER_SLOT, _upgrader);
emit ConfigUpdate(UpdateType.UPGRADER, abi.encode(_upgrader));
}
}
......@@ -2,16 +2,13 @@
pragma solidity 0.8.15;
// Contracts
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IOptimismPortalInterop as IOptimismPortal } from "src/L1/interfaces/IOptimismPortalInterop.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
import { ConfigType } from "src/L2/L1BlockInterop.sol";
// Libraries
import { Constants } from "src/libraries/Constants.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { StaticConfig } from "src/libraries/StaticConfig.sol";
import { Storage } from "src/libraries/Storage.sol";
import { Types } from "src/libraries/Types.sol";
// Interfaces
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
......@@ -28,24 +25,20 @@ contract SystemConfigInterop is SystemConfig {
0x1708e077affb93e89be2665fb0fb72581be66f84dc00d25fed755ae911905b1c;
/// @notice Initializer.
/// @param _owner Initial owner of the contract.
/// @param _roles Initial roles.
/// @param _basefeeScalar Initial basefee scalar value.
/// @param _blobbasefeeScalar Initial blobbasefee scalar value.
/// @param _batcherHash Initial batcher hash.
/// @param _gasLimit Initial gas limit.
/// @param _unsafeBlockSigner Initial unsafe block signer address.
/// @param _config Initial ResourceConfig.
/// @param _batchInbox Batch inbox address. An identifier for the op-node to find
/// canonical data.
/// @param _addresses Set of L1 contract addresses. These should be the proxies.
/// @param _dependencyManager The addressed allowed to add/remove from the dependency set
function initialize(
address _owner,
SystemConfig.Roles memory _roles,
uint32 _basefeeScalar,
uint32 _blobbasefeeScalar,
bytes32 _batcherHash,
uint64 _gasLimit,
address _unsafeBlockSigner,
IResourceMetering.ResourceConfig memory _config,
address _batchInbox,
SystemConfig.Addresses memory _addresses,
......@@ -55,12 +48,10 @@ contract SystemConfigInterop is SystemConfig {
{
// This method has an initializer modifier, and will revert if already initialized.
initialize({
_owner: _owner,
_roles: _roles,
_basefeeScalar: _basefeeScalar,
_blobbasefeeScalar: _blobbasefeeScalar,
_batcherHash: _batcherHash,
_gasLimit: _gasLimit,
_unsafeBlockSigner: _unsafeBlockSigner,
_config: _config,
_batchInbox: _batchInbox,
_addresses: _addresses
......@@ -68,38 +59,9 @@ contract SystemConfigInterop is SystemConfig {
Storage.setAddress(DEPENDENCY_MANAGER_SLOT, _dependencyManager);
}
/// @custom:semver +interop-beta.3
/// @custom:semver +interop-beta.4
function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop-beta.3");
}
/// @notice Internal setter for the gas paying token address, includes validation.
/// The token must not already be set and must be non zero and not the ether address
/// to set the token address. This prevents the token address from being changed
/// and makes it explicitly opt-in to use custom gas token. Additionally,
/// OptimismPortal's address must be non zero, since otherwise the call to set the
/// config for the gas paying token to OptimismPortal will fail.
/// @param _token Address of the gas paying token.
function _setGasPayingToken(address _token) internal override {
if (_token != address(0) && _token != Constants.ETHER && !isCustomGasToken()) {
require(
ERC20(_token).decimals() == GAS_PAYING_TOKEN_DECIMALS, "SystemConfig: bad decimals of gas paying token"
);
bytes32 name = GasPayingToken.sanitize(ERC20(_token).name());
bytes32 symbol = GasPayingToken.sanitize(ERC20(_token).symbol());
// Set the gas paying token in storage and in the OptimismPortal.
GasPayingToken.set({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol });
IOptimismPortal(payable(optimismPortal())).setConfig(
ConfigType.SET_GAS_PAYING_TOKEN,
StaticConfig.encodeSetGasPayingToken({
_token: _token,
_decimals: GAS_PAYING_TOKEN_DECIMALS,
_name: name,
_symbol: symbol
})
);
}
return string.concat(super.version(), "+interop-beta.4");
}
/// @notice Adds a chain to the interop dependency set. Can only be called by the dependency manager.
......@@ -107,7 +69,7 @@ contract SystemConfigInterop is SystemConfig {
function addDependency(uint256 _chainId) external {
require(msg.sender == dependencyManager(), "SystemConfig: caller is not the dependency manager");
IOptimismPortal(payable(optimismPortal())).setConfig(
ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)
Types.ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)
);
}
......@@ -116,7 +78,7 @@ contract SystemConfigInterop is SystemConfig {
function removeDependency(uint256 _chainId) external {
require(msg.sender == dependencyManager(), "SystemConfig: caller is not the dependency manager");
IOptimismPortal(payable(optimismPortal())).setConfig(
ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)
Types.ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)
);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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