Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Isthmus Contracts #12746

Merged
merged 63 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6fff341
feat: Isthmus Contracts work squashed
maurelian Oct 30, 2024
0853741
debug: Add fee admin to intent
maurelian Oct 31, 2024
8571d9c
fix: fee vault immutable checks no longer necessary
maurelian Oct 31, 2024
fbb7ff8
fix: TestConfigDataMarshalUnmarshal
maurelian Oct 31, 2024
b4b27af
fix: immutable check for L2ProxyAdmin owner
maurelian Oct 31, 2024
243d7d0
fix: SystemConfigFeeAdmin naming in opchain.go
maurelian Oct 31, 2024
adc9938
feat: op-deployer - get SystemConfigFeeAdmin from intent.Roles
maurelian Oct 31, 2024
3d13efb
remove dead comments
maurelian Oct 31, 2024
84c2aa6
feat: resolve feeAdmin setting todo coment
maurelian Nov 1, 2024
6e0e438
feat: move unsafeBLockSigner into SystemConfig.Roles struct
maurelian Nov 1, 2024
8fbda76
feat: move batcherHash into SystemConfig.Roles struct
maurelian Nov 1, 2024
0cba3b0
fix: Add missing feeAdmin setter in DeployOpChain test
maurelian Nov 1, 2024
f4cff03
fix: SystemConfig.init in specs
maurelian Nov 1, 2024
303bb37
feat: resolve todo
maurelian Nov 1, 2024
ca93ec5
feat: resolve some todos
maurelian Nov 1, 2024
fa19f40
feat: Natspec in StaticConfig
maurelian Nov 1, 2024
251eb9f
feat: resolve some todos
maurelian Nov 1, 2024
6e04e02
fix: test_getConfigRoundtripGasPayingToken_succeeds with normalizeSma…
maurelian Nov 1, 2024
93b066a
pre-pr
maurelian Nov 1, 2024
1372114
test: Implement roll and reset prevBought gas in SystemConfig Test's …
maurelian Nov 1, 2024
e9e868a
feat: Add natspec on SystemConfig.Roles
maurelian Nov 1, 2024
c42f365
feat: Fix all incomplete @notice natspec comments
maurelian Nov 1, 2024
9e63bfd
feat: systemConfigFeeAdmin name in opcm
maurelian Nov 1, 2024
696a36c
rebuild snapshots
maurelian Nov 1, 2024
c20eed3
Add ArtifactsFromURL utility
mslipper Nov 1, 2024
c43c61b
add configurability to createEnv
mslipper Nov 1, 2024
4194c00
clean up env.go
mslipper Nov 1, 2024
45ce943
fix apply test
mslipper Nov 1, 2024
eaf9964
fix: TestInteropDeployment
maurelian Nov 1, 2024
9a92a3c
fix: TestApplyExistingOPCM
maurelian Nov 1, 2024
6ec8e2b
fix: unchecked return on checkImmutable
maurelian Nov 1, 2024
4875966
fix: goimports env.go
maurelian Nov 1, 2024
2acb8d3
fix: Add devkey for SystemConfigFeeAdmin
maurelian Nov 1, 2024
6e023ae
fix: TestInteropDeployment
maurelian Nov 1, 2024
a7492b4
fix: TestInteropDevRecipe
maurelian Nov 1, 2024
730d653
feat: use base CDM interface in L1Block
maurelian Nov 3, 2024
0b4427e
feat: configure L1 Block config values in L2Genesis
maurelian Nov 4, 2024
a9555c8
feat: document Isthmus upgrade transactions on `setIsthmus()`
maurelian Nov 4, 2024
ac14d73
semver fixes
maurelian Nov 5, 2024
6cc22ac
feat: L2 Genesis with cheated config in L1Block
maurelian Nov 5, 2024
204fd03
ok: how'd those warnings get in there in the first place?
maurelian Nov 5, 2024
56e89ea
chore: update semver-lock
maurelian Nov 5, 2024
7dfa5ea
works
maurelian Nov 5, 2024
0c3ad98
allocs build, cfg calls commented out cuz they fail
maurelian Nov 5, 2024
10208c9
fix: read DeployConfig before it gets deleted
maurelian Nov 5, 2024
81e004a
fix: test_allocs_size
maurelian Nov 5, 2024
7a4ddcd
fix: restore l1 deps
maurelian Nov 5, 2024
e1193b3
fix: test_getConfigRoundtripGasPayingToken_succeeds disallow eth address
maurelian Nov 6, 2024
e1ddebd
fix: update test_proveWithdrawalTransaction_benchmark
maurelian Nov 6, 2024
3027d3a
feat: Add Isthmus to Config.sol
maurelian Nov 6, 2024
96d34c9
feat: hoist L1Block population above allocs writes
maurelian Nov 6, 2024
159ed63
chore: delete debug logs
maurelian Nov 6, 2024
1035652
WIP: update SystemConfig bindings and go usage
maurelian Nov 6, 2024
960fe16
fix: go linting
maurelian Nov 6, 2024
9210a7d
feat: deposit setGasPayingToken as first call in SystemConfig.init
maurelian Nov 6, 2024
834d794
semver lock
maurelian Nov 6, 2024
41c0ba0
TODO in L2Genesis
maurelian Nov 6, 2024
b53dec4
chore: semver
maurelian Nov 6, 2024
dc6ba4c
fix: Remove outdated comments
maurelian Nov 6, 2024
8c7e192
feat: extract logic into _setNetworkConfig()
maurelian Nov 6, 2024
33b0792
test: Add total gas usage test
maurelian Nov 7, 2024
5c17161
remove dead comment
maurelian Nov 7, 2024
65f03fa
ci: reduce heavy fuzz runs temporarily
maurelian Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .semgrep/rules/sol-rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions .semgrep/tests/sol-rules.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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: ");

Expand Down Expand Up @@ -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: ");

Expand Down
2 changes: 1 addition & 1 deletion bedrock-devnet/devnet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
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"
Expand Down
4 changes: 4 additions & 0 deletions op-chain-ops/devkeys/devkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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))
}
Expand Down
3 changes: 3 additions & 0 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"l1GenesisBlockGasLimit": "0x1c9c380",
"l1GenesisBlockDifficulty": "0x1",
"finalSystemOwner": "0xbcd4042de499d14e55001ccbb24a551f3b954096",
"systemConfigFeeAdmin": "0xbcd4042de499d14e55001ccbb24a551f3b954096",
"superchainConfigGuardian": "0x0000000000000000000000000000000000000112",
"finalizationPeriodSeconds": 2,
"l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
Expand Down
9 changes: 5 additions & 4 deletions op-chain-ops/interopgen/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@ func (c *SuperchainConfig) Check(log log.Logger) error {
}

type L2Config struct {
Deployer common.Address // account used to deploy contracts to L2
Proposer common.Address
Challenger common.Address
SystemConfigOwner common.Address
Deployer common.Address // account used to deploy contracts to L2
Proposer common.Address
Challenger common.Address
SystemConfigOwner common.Address
SystemConfigFeeAdmin common.Address
genesis.L2InitializationConfig
Prefund map[common.Address]*big.Int
SaltMixer string
Expand Down
40 changes: 21 additions & 19 deletions op-chain-ops/interopgen/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,25 +200,27 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme

l1Host.SetTxOrigin(cfg.Deployer)

output, err := opcm.DeployOPChainV160(l1Host, opcm.DeployOPChainInputV160{
OpChainProxyAdminOwner: cfg.ProxyAdminOwner,
SystemConfigOwner: cfg.SystemConfigOwner,
Batcher: cfg.BatchSenderAddress,
UnsafeBlockSigner: cfg.P2PSequencerAddress,
Proposer: cfg.Proposer,
Challenger: cfg.Challenger,
BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar,
BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar,
L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID),
OpcmProxy: superDeployment.OpcmProxy,
SaltMixer: cfg.SaltMixer,
GasLimit: cfg.GasLimit,
DisputeGameType: cfg.DisputeGameType,
DisputeAbsolutePrestate: cfg.DisputeAbsolutePrestate,
DisputeMaxGameDepth: cfg.DisputeMaxGameDepth,
DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration,
output, err := opcm.DeployOPChainIsthmus(l1Host, opcm.DeployOPChainInputIsthmus{
DeployOPChainInputV160: opcm.DeployOPChainInputV160{
OpChainProxyAdminOwner: cfg.ProxyAdminOwner,
SystemConfigOwner: cfg.SystemConfigOwner,
Batcher: cfg.BatchSenderAddress,
UnsafeBlockSigner: cfg.P2PSequencerAddress,
Proposer: cfg.Proposer,
Challenger: cfg.Challenger,
BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar,
BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar,
L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID),
OpcmProxy: superDeployment.OpcmProxy,
SaltMixer: cfg.SaltMixer,
GasLimit: cfg.GasLimit,
DisputeGameType: cfg.DisputeGameType,
DisputeAbsolutePrestate: cfg.DisputeAbsolutePrestate,
DisputeMaxGameDepth: cfg.DisputeMaxGameDepth,
DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration},
SystemConfigFeeAdmin: cfg.SystemConfigFeeAdmin,
})
if err != nil {
return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err)
Expand Down
13 changes: 9 additions & 4 deletions op-chain-ops/interopgen/recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Deployer: deployer,
Proposer: proposer,
Challenger: challenger,
SystemConfigOwner: systemConfigOwner,
SystemConfigFeeAdmin: systemConfigFeeAdmin,
L2InitializationConfig: genesis.L2InitializationConfig{
DevDeployConfig: genesis.DevDeployConfig{
FundDevAccounts: true,
Expand Down
116 changes: 75 additions & 41 deletions op-deployer/pkg/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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)

Expand All @@ -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(
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
})
}
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -581,8 +608,8 @@ func createEnv(
}

bundle := pipeline.ArtifactsBundle{
L1: artifactsFS,
L2: artifactsFS,
L1: l1AFS,
L2: l2AFS,
}

return env, bundle, host
Expand Down Expand Up @@ -632,13 +659,14 @@ func newChainIntent(t *testing.T, dk *devkeys.MnemonicDevKeys, l1ChainID *big.In
Eip1559Denominator: 50,
Eip1559Elasticity: 6,
Roles: state.ChainRoles{
L1ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
L2ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)),
SystemConfigOwner: addrFor(t, dk, devkeys.SystemConfigOwner.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)),
Challenger: addrFor(t, dk, devkeys.ChallengerRole.Key(l1ChainID)),
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)),
Challenger: addrFor(t, dk, devkeys.ChallengerRole.Key(l1ChainID)),
},
}
}
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down
Loading