@@ -17,29 +17,35 @@ import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC2
1717import { L1Block } from "src/L2/L1Block.sol " ;
1818import { GovernanceToken } from "src/governance/GovernanceToken.sol " ;
1919import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol " ;
20+ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol " ;
2021
2122interface IInitializable {
2223 function initialize (address _addr ) external ;
2324}
2425
2526/// @dev The general flow of adding a predeploy is:
26- /// 1. _setProxies uses vm.etch to set the Proxy.sol deployed bytecode for proxy address `0x420...000` to `0x420...000 + PROXY_COUNT - 1`.
27+ /// 1. _setPredeployProxies uses vm.etch to set the Proxy.sol deployed bytecode for proxy address `0x420...000` to
28+ /// `0x420...000 + PROXY_COUNT - 1`.
2729/// Additionally, the PROXY_ADMIN_ADDRESS and PROXY_IMPLEMENTATION_ADDRESS storage slots are set for the proxy
2830/// address.
29- /// 2. vm.etch sets the deployed bytecode for each predeploy at the implementation address (i.e. `0xc0d3` namespace).
30- /// 3. The `initialize` method is called at the implementation address with zero/dummy vaules if it exists.
31- /// 4. The `initialize` method is called at the proxy address with actual vaules if it exists.
31+ /// 2. `vm.etch` sets the deployed bytecode for each predeploy at the implementation address (i.e. `0xc0d3`
32+ /// namespace).
33+ /// 3. The `initialize` method is called at the implementation address with zero/dummy vaules if the method exists.
34+ /// 4. The `initialize` method is called at the proxy address with actual vaules if the method exists.
3235/// 5. A `require` check to verify the expected implementation address is set for the proxy.
3336/// @notice The following safety invariants are used when setting state:
3437/// 1. `vm.getDeployedBytecode` can only be used with `vm.etch` when there are no side
3538/// effects in the constructor and no immutables in the bytecode.
3639/// 2. A contract must be deployed using the `new` syntax if there are immutables in the code.
3740/// Any other side effects from the init code besides setting the immutables must be cleaned up afterwards.
38- /// 3. A contract is deployed using the `new` syntax because it's not proxied, but still needs to be set
39- /// at a specific address. Because just deploying a new instance doesn't give us the contract at our desired
40- /// address,
41- /// we must use `vm.etch` to set the deployed bytecode, and `vm.store` to set any storage slots. Lastly, we reset
42- /// the account the contract was initially deployed by so it's not included in the `vm.dumpState`.
41+ /// 3. A contract is deployed using the `new` syntax, however it's not proxied and is still expected to exist at
42+ /// a
43+ /// specific implementation address (i.e. `0xc0d3` namespace). In this case we deploy an instance of the
44+ /// contract
45+ /// using `new` syntax, use `contract.code` to retrieve it's deployed bytecode, `vm.etch` the bytecode at the
46+ /// expected implementation address, and `vm.store` to set any storage slots that are
47+ /// expected to be set after a new deployment. Lastly, we reset the account code and storage slots the contract
48+ /// was initially deployed to so it's not included in the `vm.dumpState`.
4349contract L2Genesis is Script , Artifacts {
4450 uint256 constant PROXY_COUNT = 2048 ;
4551 uint256 constant PRECOMPILE_COUNT = 256 ;
@@ -54,6 +60,20 @@ contract L2Genesis is Script, Artifacts {
5460 /// @notice The storage slot that holds the address of the owner.
5561 /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)`
5662 bytes32 internal constant PROXY_ADMIN_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 ;
63+ uint80 internal constant DEV_ACCOUNT_FUND_AMT = 10_000 ether ;
64+ /// @notice Default Anvil dev accounts. Only funded if `cfg.fundDevAccounts == true`.
65+ address [10 ] internal devAccounts = [
66+ 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 ,
67+ 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 ,
68+ 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC ,
69+ 0x90F79bf6EB2c4f870365E785982E1f101E93b906 ,
70+ 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 ,
71+ 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc ,
72+ 0x976EA74026E726554dB657fA54763abd0C3a0aa9 ,
73+ 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 ,
74+ 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f ,
75+ 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720
76+ ];
5777
5878 string internal outfile;
5979
@@ -77,9 +97,13 @@ contract L2Genesis is Script, Artifacts {
7797 /// to generate a L2 genesis alloc.
7898 /// @notice The alloc object is sorted numerically by address.
7999 function run () public {
80- _setPrecompiles ();
81- _setProxies ();
82- _setImplementations ();
100+ _dealEthToPrecompiles ();
101+ _setPredeployProxies ();
102+ _setPredeployImplementations ();
103+
104+ if (cfg.fundDevAccounts ()) {
105+ _fundDevAccounts ();
106+ }
83107
84108 /// Reset so its not included state dump
85109 vm.etch (address (cfg), "" );
@@ -90,7 +114,7 @@ contract L2Genesis is Script, Artifacts {
90114
91115 /// @notice Give all of the precompiles 1 wei so that they are
92116 /// not considered empty accounts.
93- function _setPrecompiles () internal {
117+ function _dealEthToPrecompiles () internal {
94118 for (uint256 i; i < PRECOMPILE_COUNT; i++ ) {
95119 vm.deal (address (uint160 (i)), 1 );
96120 }
@@ -100,7 +124,7 @@ contract L2Genesis is Script, Artifacts {
100124 /// The Proxy bytecode should be set. All proxied predeploys should have
101125 /// the 1967 admin slot set to the ProxyAdmin predeploy. All defined predeploys
102126 /// should have their implementations set.
103- function _setProxies () internal {
127+ function _setPredeployProxies () internal {
104128 bytes memory code = vm.getDeployedCode ("Proxy.sol:Proxy " );
105129 uint160 prefix = uint160 (0x420 ) << 148 ;
106130
@@ -129,7 +153,7 @@ contract L2Genesis is Script, Artifacts {
129153 /// @notice LEGACY_ERC20_ETH is not being predeployed since it's been deprecated.
130154 /// @dev Sets all the implementations for the predeploy proxies. For contracts without proxies,
131155 /// sets the deployed bytecode at their expected predeploy address.
132- function _setImplementations () internal {
156+ function _setPredeployImplementations () internal {
133157 _setLegacyMessagePasser ();
134158 _setDeployerWhitelist ();
135159 _setWETH9 ();
@@ -228,7 +252,7 @@ contract L2Genesis is Script, Artifacts {
228252 SequencerFeeVault vault = new SequencerFeeVault ({
229253 _recipient: cfg.sequencerFeeVaultRecipient (),
230254 _minWithdrawalAmount: cfg.sequencerFeeVaultMinimumWithdrawalAmount (),
231- _withdrawalNetwork: FeeVault.WithdrawalNetwork.L1
255+ _withdrawalNetwork: FeeVault.WithdrawalNetwork (cfg. sequencerFeeVaultWithdrawalNetwork ())
232256 });
233257
234258 address impl = _predeployToCodeNamespace (Predeploys.SEQUENCER_FEE_WALLET);
@@ -350,7 +374,7 @@ contract L2Genesis is Script, Artifacts {
350374 /// @notice There isn't a good way to know if the resulting revering is due to abi mismatch
351375 /// or because it's already been initialized
352376 function _verifyCantReinitialize (address _contract , address _arg ) internal {
353- vm.expectRevert ();
377+ vm.expectRevert (" Initializable: contract is already initialized " );
354378 IInitializable (_contract).initialize (_arg);
355379 }
356380
@@ -363,6 +387,15 @@ contract L2Genesis is Script, Artifacts {
363387 vm.ffi (commands);
364388 }
365389
390+ function _fundDevAccounts () internal {
391+ for (uint256 i; i < devAccounts.length ; i++ ) {
392+ console.log ("Funding dev account %s with %s ETH " , devAccounts[i], DEV_ACCOUNT_FUND_AMT / 1e18 );
393+ vm.deal (devAccounts[i], DEV_ACCOUNT_FUND_AMT);
394+ }
395+
396+ _checkDevAccountsFunded ();
397+ }
398+
366399 //////////////////////////////////////////////////////
367400 /// Post Checks
368401 //////////////////////////////////////////////////////
@@ -384,4 +417,16 @@ contract L2Genesis is Script, Artifacts {
384417 _verifyCantReinitialize (_impl, address (0 ));
385418 _verifyCantReinitialize (Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, Predeploys.L2_STANDARD_BRIDGE);
386419 }
420+
421+ function _checkDevAccountsFunded () internal view {
422+ for (uint256 i; i < devAccounts.length ; i++ ) {
423+ if (devAccounts[i].balance != DEV_ACCOUNT_FUND_AMT) {
424+ revert (
425+ string .concat (
426+ "Dev account not funded with expected amount of ETH: " , Strings.toHexString (devAccounts[i])
427+ )
428+ );
429+ }
430+ }
431+ }
387432}
0 commit comments