Skip to content

Commit a1e846d

Browse files
authored
contracts-bedrock: cleanup predeploys solidity test (#8933)
* contracts-bedrock: cleanup predeploys solidity test Contributors to the smart contracts have way too many steps to get their PR over the line. This migrates some of the `check-l2` script to solidity. I believe that we can fully delete `check-l2` but want to follow up in an additional PR to ensure that we have the same functionality. Completely deleting `check-l2` was unblocked by #8911. The functionality that is added to the solidity here was removed from the `check-l2` script. * op-chain-ops: remove dead code * op-chain-ops: fix build issue
1 parent 67e8b98 commit a1e846d

File tree

2 files changed

+50
-111
lines changed

2 files changed

+50
-111
lines changed

op-chain-ops/cmd/check-l2/main.go

-103
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
2323
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
2424
"github.com/ethereum-optimism/optimism/op-chain-ops/clients"
25-
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
2625
"github.com/ethereum/go-ethereum/common"
2726
"github.com/ethereum/go-ethereum/ethclient"
2827
"github.com/ethereum/go-ethereum/log"
@@ -76,29 +75,6 @@ func entrypoint(ctx *cli.Context) error {
7675
}
7776

7877
log.Info("Checking predeploy proxy config")
79-
g := new(errgroup.Group)
80-
81-
// Check that all proxies are configured correctly
82-
// Do this in parallel but not too quickly to allow for
83-
// querying against rate limiting RPC backends
84-
count := uint64(2048)
85-
for i := uint64(0); i < count; i++ {
86-
i := i
87-
if i%4 == 0 {
88-
log.Info("Checking proxy", "index", i, "total", count)
89-
if err := g.Wait(); err != nil {
90-
return err
91-
}
92-
}
93-
g.Go(func() error {
94-
return checkPredeploy(clients.L2Client, i)
95-
})
96-
}
97-
98-
if err := g.Wait(); err != nil {
99-
return err
100-
}
101-
log.Info("All predeploy proxies are set correctly")
10278

10379
// Check that all of the defined predeploys are set up correctly
10480
for name, pre := range predeploys.Predeploys {
@@ -110,23 +86,6 @@ func entrypoint(ctx *cli.Context) error {
11086
return nil
11187
}
11288

113-
// checkPredeploy ensures that the predeploy at index i has the correct proxy admin set
114-
func checkPredeploy(client *ethclient.Client, i uint64) error {
115-
bigAddr := new(big.Int).Or(genesis.BigL2PredeployNamespace, new(big.Int).SetUint64(i))
116-
addr := common.BigToAddress(bigAddr)
117-
if pre, ok := predeploys.PredeploysByAddress[addr]; ok && pre.ProxyDisabled {
118-
return nil
119-
}
120-
admin, err := getEIP1967AdminAddress(client, addr)
121-
if err != nil {
122-
return err
123-
}
124-
if admin != predeploys.ProxyAdminAddr {
125-
return fmt.Errorf("%s does not have correct proxy admin set", addr)
126-
}
127-
return nil
128-
}
129-
13089
// checkPredeployConfig checks that the defined predeploys are configured correctly
13190
func checkPredeployConfig(client *ethclient.Client, name string) error {
13291
predeploy := predeploys.Predeploys[name]
@@ -136,50 +95,6 @@ func checkPredeployConfig(client *ethclient.Client, name string) error {
13695
p := predeploy.Address
13796

13897
g := new(errgroup.Group)
139-
if !predeploy.ProxyDisabled {
140-
// Check that an implementation is set. If the implementation has been upgraded,
141-
// it will be considered non-standard. Ensure that there is code set at the implementation.
142-
g.Go(func() error {
143-
impl, err := getEIP1967ImplementationAddress(client, p)
144-
if err != nil {
145-
return err
146-
}
147-
log.Info(name, "implementation", impl.Hex())
148-
standardImpl, err := genesis.AddressToCodeNamespace(p)
149-
if err != nil {
150-
return err
151-
}
152-
if impl != standardImpl {
153-
log.Warn(name + " does not have the standard implementation")
154-
}
155-
implCode, err := client.CodeAt(context.Background(), impl, nil)
156-
if err != nil {
157-
return err
158-
}
159-
if len(implCode) == 0 {
160-
return fmt.Errorf("%s implementation is not deployed", name)
161-
}
162-
return nil
163-
})
164-
165-
// Ensure that the code is set to the proxy bytecode as expected
166-
// This will not work against production networks where the bytecode
167-
// has deviated from the current bytecode. We need a more reliable way to check for this.
168-
g.Go(func() error {
169-
proxyCode, err := client.CodeAt(context.Background(), p, nil)
170-
if err != nil {
171-
return err
172-
}
173-
proxy, err := bindings.GetDeployedBytecode("Proxy")
174-
if err != nil {
175-
return err
176-
}
177-
if !bytes.Equal(proxyCode, proxy) {
178-
return fmt.Errorf("%s does not have the standard proxy code", name)
179-
}
180-
return nil
181-
})
182-
}
18398

18499
// Check the predeploy specific config is correct
185100
g.Go(func() error {
@@ -981,24 +896,6 @@ func checkPredeployBytecode(addr common.Address, client *ethclient.Client, expec
981896
return nil
982897
}
983898

984-
func getEIP1967AdminAddress(client *ethclient.Client, addr common.Address) (common.Address, error) {
985-
slot, err := client.StorageAt(context.Background(), addr, genesis.AdminSlot, nil)
986-
if err != nil {
987-
return common.Address{}, err
988-
}
989-
admin := common.BytesToAddress(slot)
990-
return admin, nil
991-
}
992-
993-
func getEIP1967ImplementationAddress(client *ethclient.Client, addr common.Address) (common.Address, error) {
994-
slot, err := client.StorageAt(context.Background(), addr, genesis.ImplementationSlot, nil)
995-
if err != nil {
996-
return common.Address{}, err
997-
}
998-
impl := common.BytesToAddress(slot)
999-
return impl, nil
1000-
}
1001-
1002899
// getInitialized will get the initialized value in storage of a contract.
1003900
// This is an incrementing number that starts at 1 and increments each time that
1004901
// the contract is upgraded.

packages/contracts-bedrock/test/Predeploys.t.sol

+50-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,38 @@ import { CommonTest } from "test/setup/CommonTest.sol";
55
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
66
import { Predeploys } from "src/libraries/Predeploys.sol";
77

8+
/// @title PredeploysTest
89
contract PredeploysTest is CommonTest {
10+
/// @dev Function to compute the expected address of the predeploy implementation
11+
/// in the genesis state.
12+
function _predeployToCodeNamespace(address _addr) internal pure returns (address) {
13+
return address(
14+
uint160(uint256(uint160(_addr)) & 0xffff | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000)))
15+
);
16+
}
17+
18+
/// @dev Returns true if the address is a predeploy.
19+
function _isPredeploy(address _addr) internal pure returns (bool) {
20+
return _addr == Predeploys.L2_TO_L1_MESSAGE_PASSER || _addr == Predeploys.L2_CROSS_DOMAIN_MESSENGER
21+
|| _addr == Predeploys.L2_STANDARD_BRIDGE || _addr == Predeploys.L2_ERC721_BRIDGE
22+
|| _addr == Predeploys.SEQUENCER_FEE_WALLET || _addr == Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY
23+
|| _addr == Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == Predeploys.L1_BLOCK_ATTRIBUTES
24+
|| _addr == Predeploys.GAS_PRICE_ORACLE || _addr == Predeploys.DEPLOYER_WHITELIST || _addr == Predeploys.WETH9
25+
|| _addr == Predeploys.L1_BLOCK_NUMBER || _addr == Predeploys.LEGACY_MESSAGE_PASSER
26+
|| _addr == Predeploys.PROXY_ADMIN || _addr == Predeploys.BASE_FEE_VAULT || _addr == Predeploys.L1_FEE_VAULT
27+
|| _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.SCHEMA_REGISTRY || _addr == Predeploys.EAS;
28+
}
29+
30+
/// @dev Returns true if the adress is not proxied.
31+
function _notProxied(address _addr) internal pure returns (bool) {
32+
return _addr == Predeploys.LEGACY_ERC20_ETH || _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.WETH9
33+
|| _addr == Predeploys.MultiCall3 || _addr == Predeploys.Create2Deployer || _addr == Predeploys.Safe_v130
34+
|| _addr == Predeploys.SafeL2_v130 || _addr == Predeploys.MultiSendCallOnly_v130
35+
|| _addr == Predeploys.SafeSingletonFactory || _addr == Predeploys.DeterministicDeploymentProxy
36+
|| _addr == Predeploys.MultiSend_v130 || _addr == Predeploys.Permit2 || _addr == Predeploys.SenderCreator
37+
|| _addr == Predeploys.EntryPoint;
38+
}
39+
940
/// @dev Tests that the predeploy addresses are set correctly. They have code
1041
/// and the proxied accounts have the correct admin.
1142
function test_predeploysSet_succeeds() external {
@@ -15,17 +46,28 @@ contract PredeploysTest is CommonTest {
1546
address addr = address(prefix | uint160(i));
1647
bytes memory code = addr.code;
1748
assertTrue(code.length > 0);
49+
50+
bool proxied = _notProxied(addr) == false;
51+
bool isPredeploy = _isPredeploy(addr);
52+
1853
// Skip the accounts that do not have a proxy
19-
if (
20-
addr == Predeploys.LEGACY_ERC20_ETH || addr == Predeploys.GOVERNANCE_TOKEN || addr == Predeploys.WETH9
21-
|| addr == Predeploys.MultiCall3 || addr == Predeploys.Create2Deployer || addr == Predeploys.Safe_v130
22-
|| addr == Predeploys.SafeL2_v130 || addr == Predeploys.MultiSendCallOnly_v130
23-
|| addr == Predeploys.SafeSingletonFactory || addr == Predeploys.DeterministicDeploymentProxy
24-
|| addr == Predeploys.MultiSend_v130 || addr == Predeploys.Permit2 || addr == Predeploys.SenderCreator
25-
|| addr == Predeploys.EntryPoint
26-
) {
54+
if (proxied == false) {
2755
continue;
2856
}
57+
58+
// Only the defined predeploys have their implementation slot set
59+
if (proxied && isPredeploy) {
60+
assertEq(
61+
EIP1967Helper.getImplementation(addr),
62+
_predeployToCodeNamespace(addr),
63+
string.concat("Implementation mismatch for ", vm.toString(addr))
64+
);
65+
}
66+
67+
// The code is a proxy
68+
assertEq(code, vm.getDeployedCode("Proxy.sol"));
69+
70+
// All of the defined predeploys have their admin set to the proxy admin
2971
assertEq(EIP1967Helper.getAdmin(addr), Predeploys.PROXY_ADMIN, "Admin mismatch");
3072
}
3173
}

0 commit comments

Comments
 (0)