Skip to content

Commit

Permalink
feat: Isthmus Contracts (#12746)
Browse files Browse the repository at this point in the history
* 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: Matthew Slipper <[email protected]>
  • Loading branch information
maurelian and mslipper authored Nov 7, 2024
1 parent 3952e60 commit dad1087
Show file tree
Hide file tree
Showing 171 changed files with 3,733 additions and 1,903 deletions.
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
1 change: 1 addition & 0 deletions op-chain-ops/genesis/testdata/test-deploy-config-full.json
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

0 comments on commit dad1087

Please sign in to comment.