@@ -23,6 +23,7 @@ import {
23
23
getExpectedStorageTokenWrappedBridgeUpgradeable ,
24
24
updateExpectedStorageBridgeToken ,
25
25
getExpectedStorageAggOracleCommittee ,
26
+ getStorageTimelockAdminRoleMember ,
26
27
} from './utils' ;
27
28
import { checkParams } from '../utils' ;
28
29
import { logger } from '../logger' ;
@@ -41,6 +42,10 @@ const supportedBridgeContractsProxy = ['PolygonZkEVMBridgeV2 proxy', 'PolygonZkE
41
42
* @returns The genesis file
42
43
*/
43
44
export async function createGenesisHardhat ( _genesisBase : any , initializeParams : any , config : any ) {
45
+ let isDebug = false ;
46
+ if ( config && config . debug ) {
47
+ isDebug = config . debug ;
48
+ }
44
49
logger . info ( 'createGenesisHardhat tool' ) ;
45
50
46
51
/// //////////////////////////
@@ -113,27 +118,27 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
113
118
}
114
119
115
120
// TIMELOCK_OWNER
116
- // let timelockOwner;
117
- // // Set the default owner from the genesis base
118
- // if (config.timelock === undefined || config.timelock.owner === undefined) {
119
- // timelockOwner = genesisBaseAddresses.deployerAddress;
120
- // } else {
121
- // // Check if the owner is a valid address
122
- // if (!ethers.isAddress(config.timelock.owner)) {
123
- // throw new Error('timelock owner must be a valid address');
124
- // }
125
- // timelockOwner = config.timelock.owner;
126
- // }
121
+ let timelockOwner ;
122
+ // Set the default owner from the genesis base
123
+ if ( config . timelock === undefined || config . timelock . owner === undefined ) {
124
+ timelockOwner = genesisBaseAddresses . deployerAddress ;
125
+ } else {
126
+ // Check if the owner is a valid address
127
+ if ( ! ethers . isAddress ( config . timelock . owner ) ) {
128
+ throw new Error ( 'timelock owner must be a valid address' ) ;
129
+ }
130
+ timelockOwner = config . timelock . owner ;
131
+ }
127
132
128
133
/// ///////////////////////////////////
129
134
/// DEPLOY SOVEREIGN CONTRACTS ///
130
135
/// ///////////////////////////////////
131
136
const genesisInfo = [ ] ;
132
137
133
138
// Load deployer
134
- await ethers . provider . send ( 'hardhat_impersonateAccount' , [ genesisBaseAddresses . deployerAddress ] ) ;
135
- await ethers . provider . send ( 'hardhat_setBalance' , [ genesisBaseAddresses . deployerAddress , '0xffffffffffffffff' ] ) ; // 18 ethers aprox
136
- const deployer = await ethers . getSigner ( genesisBaseAddresses . deployerAddress ) ;
139
+ await ethers . provider . send ( 'hardhat_impersonateAccount' , [ timelockOwner ] ) ;
140
+ await ethers . provider . send ( 'hardhat_setBalance' , [ timelockOwner , '0xffffffffffffffff' ] ) ; // 18 ethers aprox
141
+ const deployer = await ethers . getSigner ( timelockOwner ) ;
137
142
138
143
// deploy BridgeL2SovereignChain
139
144
const BridgeL2SovereignChainFactory = await ethers . getContractFactory (
@@ -290,6 +295,16 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
290
295
await proxyAdminInstance . connect ( deployer ) . transferOwnership ( genesisBaseAddresses . timelockAddress as string )
291
296
) . wait ( ) ;
292
297
298
+ // Set timelock role with timelockAddress from genesisBaseAddresses
299
+ const txTimelockAdminRole = await timelockContract . connect ( deployer ) . grantRole (
300
+ ethers . id ( 'TIMELOCK_ADMIN_ROLE' ) ,
301
+ genesisBaseAddresses . timelockAddress , // timelockAddress from genesisBaseAddresses
302
+ ) ;
303
+ const txRevokeTimelockAdminRole = await timelockContract . connect ( deployer ) . revokeRole (
304
+ ethers . id ( 'TIMELOCK_ADMIN_ROLE' ) ,
305
+ timelockContract . target , // Revoke the role from the deployer
306
+ ) ;
307
+
293
308
/// /////////////////////////////////
294
309
/// SANITY CHECKS DEPLOYMENT ///
295
310
/// /////////////////////////////////
@@ -308,6 +323,12 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
308
323
expect ( globalExitRootUpdater ) . to . equal ( await gerManagerContract . globalExitRootUpdater ( ) ) ;
309
324
expect ( globalExitRootRemover ) . to . equal ( await gerManagerContract . globalExitRootRemover ( ) ) ;
310
325
326
+ // Check AggOracleCommittee params
327
+ if ( initializeParams . useAggOracleCommittee === true ) {
328
+ expect ( initializeParams . aggOracleOwner ) . to . equal ( await aggOracleCommitteeContract . owner ( ) ) ;
329
+ expect ( initializeParams . quorum ) . to . equal ( await aggOracleCommitteeContract . quorum ( ) ) ;
330
+ }
331
+
311
332
/// //////////////////////////////
312
333
/// SANITY CHECKS STORAGE ///
313
334
/// //////////////////////////////
@@ -468,13 +489,18 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
468
489
const timelockStorageWrites = await getTraceStorageWrites ( txDeployTimelockHash ) ;
469
490
const depthTimelockStorageWrites = 1 ;
470
491
storageModifications . PolygonZkEVMTimelock = timelockStorageWrites [ depthTimelockStorageWrites ] ;
471
-
472
- // Output the storage modifications JSON
473
- logger . info ( 'Writing storage modifications JSON to file...' ) ;
474
- await fs . writeFileSync (
475
- path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/storageModifications.json' ) ,
476
- JSON . stringify ( storageModifications , null , 2 ) ,
492
+ const timelockStorageAdmin = ( await getTraceStorageWrites ( txTimelockAdminRole . hash ) ) [ depthTimelockStorageWrites ] ;
493
+ const timelockStorageRevokeAdmin = ( await getTraceStorageWrites ( txRevokeTimelockAdminRole . hash ) ) [ depthTimelockStorageWrites ] ;
494
+ expect ( timelockStorageAdmin [ getStorageTimelockAdminRoleMember ( genesisBaseAddresses . timelockAddress ) ] ) . to . equal (
495
+ '0x0000000000000000000000000000000000000000000000000000000000000001' ,
496
+ ) ;
497
+ expect ( timelockStorageRevokeAdmin [ getStorageTimelockAdminRoleMember ( timelockContract . target ) ] ) . to . equal (
498
+ '0x0000000000000000000000000000000000000000000000000000000000000000' ,
477
499
) ;
500
+ storageModifications . PolygonZkEVMTimelock [ getStorageTimelockAdminRoleMember ( timelockContract . target ) ] =
501
+ '0x0000000000000000000000000000000000000000000000000000000000000000' ;
502
+ storageModifications . PolygonZkEVMTimelock [ getStorageTimelockAdminRoleMember ( genesisBaseAddresses . timelockAddress ) ] =
503
+ '0x0000000000000000000000000000000000000000000000000000000000000001' ;
478
504
479
505
/// /////////////////////////////////////////////////
480
506
/// BUILD EXPECTED STORAGE MODIFICATIONS JSON ///
@@ -551,11 +577,8 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
551
577
// PolygonZkEVMTimelock
552
578
expectedStorageModifications . PolygonZkEVMTimelock = getExpectedStoragePolygonZkEVMTimelock (
553
579
timelockMinDelay ,
554
- initializeParams ,
555
- ) ;
556
- await fs . writeFileSync (
557
- path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/expectedStorageModifications.json' ) ,
558
- JSON . stringify ( expectedStorageModifications , null , 2 ) ,
580
+ genesisBaseAddresses . timelockAddress ,
581
+ timelockContract . target ,
559
582
) ;
560
583
561
584
/// //////////////////////////////
@@ -642,10 +665,23 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
642
665
timelockContract . target ,
643
666
) ;
644
667
645
- await fs . writeFileSync (
646
- path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/actualStorage.json' ) ,
647
- JSON . stringify ( actualStorage , null , 2 ) ,
648
- ) ;
668
+ if ( isDebug ) {
669
+ logger . info ( '**DEBUG**: Writing actual storage JSON to file...' ) ;
670
+ await fs . writeFileSync (
671
+ path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/actualStorage.json' ) ,
672
+ JSON . stringify ( actualStorage , null , 2 ) ,
673
+ ) ;
674
+ logger . info ( '**DEBUG**: Writing expected storage modifications JSON to file...' ) ;
675
+ await fs . writeFileSync (
676
+ path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/expectedStorageModifications.json' ) ,
677
+ JSON . stringify ( expectedStorageModifications , null , 2 ) ,
678
+ ) ;
679
+ logger . info ( '**DEBUG**: Writing storage modifications JSON to file...' ) ;
680
+ await fs . writeFileSync (
681
+ path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/storageModifications.json' ) ,
682
+ JSON . stringify ( storageModifications , null , 2 ) ,
683
+ ) ;
684
+ }
649
685
650
686
let equal = deepEqual ( storageModifications , expectedStorageModifications ) ;
651
687
if ( ! equal ) {
@@ -660,6 +696,12 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
660
696
logger . info ( 'Actual storage matches expected storage' ) ;
661
697
}
662
698
699
+ logger . info ( 'Writing storage modifications JSON to file...' ) ;
700
+ await fs . writeFileSync (
701
+ path . join ( __dirname , '../../tools/createSovereignGenesisHardhat/storageModifications.json' ) ,
702
+ JSON . stringify ( storageModifications , null , 2 ) ,
703
+ ) ;
704
+
663
705
/// ///////////////////////////
664
706
/// BUILD GENESIS FILE ///
665
707
/// ///////////////////////////
@@ -675,12 +717,12 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
675
717
const bridgeL2SovereignChainImplementation = newGenesis . genesis . find ( function ( obj ) {
676
718
return supportedBridgeContracts . includes ( obj . contractName ) ;
677
719
} ) ;
678
- // Update the contract name and bytecode
720
+ // Update the contract name, bytecode, storage and nonce
721
+ // Address is not modified because it must match the L1 address
679
722
bridgeL2SovereignChainImplementation . contractName = GENESIS_CONTRACT_NAMES . SOVEREIGN_BRIDGE_IMPLEMENTATION ;
680
723
bridgeL2SovereignChainImplementation . bytecode = await ethers . provider . getCode (
681
724
await upgrades . erc1967 . getImplementationAddress ( sovereignChainBridgeContract . target ) ,
682
725
) ;
683
- // Update the storage and nonce
684
726
bridgeL2SovereignChainImplementation . storage = storageModifications . BridgeL2SovereignChain_Implementation ;
685
727
bridgeL2SovereignChainImplementation . nonce = await ethers . provider . getTransactionCount (
686
728
await upgrades . erc1967 . getImplementationAddress ( sovereignChainBridgeContract . target ) ,
@@ -694,8 +736,10 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
694
736
const bridgeL2SovereignChain = newGenesis . genesis . find ( function ( obj ) {
695
737
return supportedBridgeContractsProxy . includes ( obj . contractName ) ;
696
738
} ) ;
697
- // Update the contract name, storage and nonce
739
+ // Update the contract name, bytecode, storage and nonce
698
740
bridgeL2SovereignChain . contractName = GENESIS_CONTRACT_NAMES . SOVEREIGN_BRIDGE_PROXY ;
741
+ bridgeL2SovereignChain . bytecode = await ethers . provider . getCode ( sovereignChainBridgeContract . target ) ;
742
+ // The storage is the storage modified during deployment and initialization.
699
743
bridgeL2SovereignChain . storage = {
700
744
...storageModifications . BridgeL2SovereignChain ,
701
745
...storageModifications . BridgeL2SovereignChain_Initialization ,
@@ -706,9 +750,11 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
706
750
/// GER IMPLEMENTATION //////
707
751
/// /////////////////////////
708
752
logger . info ( 'Updating GlobalExitRootManagerL2SovereignChain implementation in genesis file...' ) ;
753
+ // Get genesis info for ger implementation
709
754
const gerManagerL2SovereignChainImplementation = newGenesis . genesis . find ( function ( obj ) {
710
755
return supportedGERManagers . includes ( obj . contractName ) ;
711
756
} ) ;
757
+ // Update the contract name, bytecode, storage and nonce
712
758
gerManagerL2SovereignChainImplementation . contractName = GENESIS_CONTRACT_NAMES . GER_L2_SOVEREIGN_IMPLEMENTATION ;
713
759
gerManagerL2SovereignChainImplementation . bytecode = await ethers . provider . getCode (
714
760
await upgrades . erc1967 . getImplementationAddress ( gerManagerContract . target ) ,
@@ -723,10 +769,14 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
723
769
/// GER PROXY ///////////////
724
770
/// /////////////////////////
725
771
logger . info ( 'Updating GlobalExitRootManagerL2SovereignChain proxy in genesis file...' ) ;
772
+ // Get genesis info for ger proxy
726
773
const gerManagerL2SovereignChain = newGenesis . genesis . find ( function ( obj ) {
727
774
return obj . contractName === GENESIS_CONTRACT_NAMES . GER_L2_PROXY ;
728
775
} ) ;
776
+ // Update the contract name, bytecode, storage and nonce
729
777
gerManagerL2SovereignChain . contractName = GENESIS_CONTRACT_NAMES . GER_L2_SOVEREIGN_PROXY ;
778
+ gerManagerL2SovereignChain . bytecode = await ethers . provider . getCode ( gerManagerContract . target ) ;
779
+ // The storage is the storage modified during deployment and initialization.
730
780
gerManagerL2SovereignChain . storage = {
731
781
...storageModifications . GlobalExitRootManagerL2SovereignChain ,
732
782
...storageModifications . GlobalExitRootManagerL2SovereignChain_Initialization ,
@@ -776,7 +826,7 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
776
826
address : tokenWrappedAddress ,
777
827
bytecode : tokenWrappedDeployedBytecode ,
778
828
} ;
779
- tokenWrappedGenesis . storage = storageModifications . TokenWrappedBridgeUpgradeable ;
829
+ tokenWrappedGenesis . storage = storageModifications . TokenWrappedBridgeUpgradeable_Implementation ;
780
830
newGenesis . genesis . push ( tokenWrappedGenesis ) ;
781
831
} else {
782
832
// Check bytecode of the TokenWrapped contract is the same as the one in the genesis
0 commit comments