Skip to content

Commit 7e88563

Browse files
committed
Update buildGenesis
1 parent fd67106 commit 7e88563

File tree

3 files changed

+127
-115
lines changed

3 files changed

+127
-115
lines changed

src/genesis-hardhat/create-genesis-hardhat.ts

Lines changed: 84 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
updateExpectedStorageBridgeToken,
2525
getExpectedStorageAggOracleCommittee,
2626
getStorageTimelockAdminRoleMember,
27+
buildGenesis,
2728
} from './utils';
2829
import { checkParams } from '../utils';
2930
import { logger } from '../logger';
@@ -357,7 +358,6 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
357358
}
358359
} catch (error) {
359360
logger.error('Could not get Bridge implementation storage writes:', error);
360-
throw new Error(error)
361361
}
362362
}
363363
// Get storage modifications for Bridge initialization
@@ -385,7 +385,7 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
385385
if (implTx) {
386386
const implStorageWrites = await getTraceStorageWrites(
387387
aggOracleCommitteeDeploymentResult.txHashes.implementation,
388-
aggOracleImplementationAddress
388+
aggOracleImplementationAddress,
389389
);
390390
storageModifications.AggOracleCommittee_Implementation = implStorageWrites;
391391
}
@@ -432,7 +432,7 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
432432
if (gerProxyTx) {
433433
const gerStorageWrites = await getTraceStorageWrites(
434434
gerDeploymentResult.txHashes.proxy,
435-
gerProxyAddress
435+
gerProxyAddress,
436436
);
437437
storageModifications.GlobalExitRootManagerL2SovereignChain = gerStorageWrites;
438438
}
@@ -690,132 +690,113 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
690690
/// ///////////////////////////
691691
logger.info('=== BUILD GENESIS FILE ===');
692692

693-
const newGenesis = _genesisBase;
693+
const genesisInfo = [];
694694

695695
/// /////////////////////////
696696
/// BRIDGE IMPLEMENTATION ///
697697
/// /////////////////////////
698698
logger.info('Updating BridgeL2SovereignChain implementation in genesis file...');
699699
// Get genesis info for bridge implementation
700-
const bridgeL2SovereignChainImplementation = newGenesis.genesis.find(function (obj) {
700+
const bridgeL2SovereignChainImplementation = _genesisBase.genesis.find(function (obj) {
701701
return supportedBridgeContracts.includes(obj.contractName);
702702
});
703-
// Update the contract name, bytecode, storage and nonce
704-
// Address is not modified because it must match the L1 address
705-
bridgeL2SovereignChainImplementation.contractName = GENESIS_CONTRACT_NAMES.SOVEREIGN_BRIDGE_IMPLEMENTATION;
706-
bridgeL2SovereignChainImplementation.bytecode = await ethers.provider.getCode(
707-
await upgrades.erc1967.getImplementationAddress(sovereignChainBridgeContract.target),
708-
);
709-
bridgeL2SovereignChainImplementation.storage = storageModifications.BridgeL2SovereignChain_Implementation;
710-
bridgeL2SovereignChainImplementation.nonce = await ethers.provider.getTransactionCount(
711-
await upgrades.erc1967.getImplementationAddress(sovereignChainBridgeContract.target),
712-
);
703+
genesisInfo.push({
704+
contractName: GENESIS_CONTRACT_NAMES.SOVEREIGN_BRIDGE_IMPLEMENTATION,
705+
genesisObject: bridgeL2SovereignChainImplementation,
706+
address: bridgeImplAddress,
707+
storage: storageModifications.BridgeL2SovereignChain_Implementation,
708+
});
713709

714710
/// /////////////////////////
715711
/// BRIDGE PROXY ////////////
716712
/// /////////////////////////
717713
logger.info('Updating BridgeL2SovereignChain proxy in genesis file...');
714+
718715
// Replace old bridge with new bridge proxy
719-
const bridgeL2SovereignChain = newGenesis.genesis.find(function (obj) {
716+
const bridgeL2SovereignChain = _genesisBase.genesis.find(function (obj) {
720717
return supportedBridgeContractsProxy.includes(obj.contractName);
721718
});
722-
// Update the contract name, bytecode, storage and nonce
723-
bridgeL2SovereignChain.contractName = GENESIS_CONTRACT_NAMES.SOVEREIGN_BRIDGE_PROXY;
724-
bridgeL2SovereignChain.bytecode = await ethers.provider.getCode(sovereignChainBridgeContract.target);
725-
// The storage is the storage modified during deployment and initialization.
726-
bridgeL2SovereignChain.storage = {
727-
...storageModifications.BridgeL2SovereignChain,
728-
...storageModifications.BridgeL2SovereignChain_Initialization,
729-
};
730-
bridgeL2SovereignChain.nonce = await ethers.provider.getTransactionCount(sovereignChainBridgeContract.target);
719+
genesisInfo.push({
720+
contractName: GENESIS_CONTRACT_NAMES.SOVEREIGN_BRIDGE_PROXY,
721+
genesisObject: bridgeL2SovereignChain,
722+
address: bridgeProxyAddress,
723+
storage: {
724+
...storageModifications.BridgeL2SovereignChain,
725+
...storageModifications.BridgeL2SovereignChain_Initialization,
726+
},
727+
});
731728

732729
/// /////////////////////////
733730
/// GER IMPLEMENTATION //////
734731
/// /////////////////////////
735732
logger.info('Updating GlobalExitRootManagerL2SovereignChain implementation in genesis file...');
736733
// Get genesis info for ger implementation
737-
const gerManagerL2SovereignChainImplementation = newGenesis.genesis.find(function (obj) {
734+
const gerManagerL2SovereignChainImplementation = _genesisBase.genesis.find(function (obj) {
738735
return supportedGERManagers.includes(obj.contractName);
739736
});
740-
// Update the contract name, bytecode, storage and nonce
741-
gerManagerL2SovereignChainImplementation.contractName = GENESIS_CONTRACT_NAMES.GER_L2_SOVEREIGN_IMPLEMENTATION;
742-
gerManagerL2SovereignChainImplementation.bytecode = await ethers.provider.getCode(
743-
await upgrades.erc1967.getImplementationAddress(gerManagerContract.target),
744-
);
745-
gerManagerL2SovereignChainImplementation.storage =
746-
storageModifications.GlobalExitRootManagerL2SovereignChain_Implementation;
747-
gerManagerL2SovereignChainImplementation.nonce = await ethers.provider.getTransactionCount(
748-
await upgrades.erc1967.getImplementationAddress(gerManagerContract.target),
749-
);
737+
genesisInfo.push({
738+
contractName: GENESIS_CONTRACT_NAMES.GER_L2_SOVEREIGN_IMPLEMENTATION,
739+
genesisObject: gerManagerL2SovereignChainImplementation,
740+
address: gerImplAddress,
741+
storage: storageModifications.GlobalExitRootManagerL2SovereignChain_Implementation,
742+
});
750743

751744
/// /////////////////////////
752745
/// GER PROXY ///////////////
753746
/// /////////////////////////
754747
logger.info('Updating GlobalExitRootManagerL2SovereignChain proxy in genesis file...');
755748
// Get genesis info for ger proxy
756-
const gerManagerL2SovereignChain = newGenesis.genesis.find(function (obj) {
749+
const gerManagerL2SovereignChain = _genesisBase.genesis.find(function (obj) {
757750
return obj.contractName === GENESIS_CONTRACT_NAMES.GER_L2_PROXY;
758751
});
759-
// Update the contract name, bytecode, storage and nonce
760-
gerManagerL2SovereignChain.contractName = GENESIS_CONTRACT_NAMES.GER_L2_SOVEREIGN_PROXY;
761-
gerManagerL2SovereignChain.bytecode = await ethers.provider.getCode(gerManagerContract.target);
762-
// The storage is the storage modified during deployment and initialization.
763-
gerManagerL2SovereignChain.storage = {
764-
...storageModifications.GlobalExitRootManagerL2SovereignChain,
765-
...storageModifications.GlobalExitRootManagerL2SovereignChain_Initialization,
766-
};
767-
gerManagerL2SovereignChain.nonce = await ethers.provider.getTransactionCount(gerManagerContract.target);
752+
genesisInfo.push({
753+
contractName: GENESIS_CONTRACT_NAMES.GER_L2_SOVEREIGN_PROXY,
754+
genesisObject: gerManagerL2SovereignChain,
755+
address: gerProxyAddress,
756+
storage: {
757+
...storageModifications.GlobalExitRootManagerL2SovereignChain,
758+
...storageModifications.GlobalExitRootManagerL2SovereignChain_Initialization,
759+
},
760+
});
768761

769762
/// /////////////////////////
770763
/// BYTECODE STORER /////////
771764
/// /////////////////////////
772765
logger.info('Updating BytecodeStorer in genesis file...');
773-
const bytecodeStorer = newGenesis.genesis.find(function (obj) {
766+
const bytecodeStorer = _genesisBase.genesis.find(function (obj) {
774767
return obj.contractName === GENESIS_CONTRACT_NAMES.BYTECODE_STORER;
775768
});
776769
const bytecodeStorerAddress = await sovereignChainBridgeContract.wrappedTokenBytecodeStorer();
777-
const bytecodeStorerDeployedBytecode = await ethers.provider.getCode(bytecodeStorerAddress);
778-
779-
// If its not contained add it to the genesis
780-
if (typeof bytecodeStorer === 'undefined') {
781-
const bytecodeStorerGenesis = {
782-
contractName: GENESIS_CONTRACT_NAMES.BYTECODE_STORER,
783-
balance: '0',
784-
nonce: '1',
785-
address: bytecodeStorerAddress,
786-
bytecode: bytecodeStorerDeployedBytecode,
787-
};
788-
newGenesis.genesis.push(bytecodeStorerGenesis);
789-
} else {
790-
bytecodeStorer.address = bytecodeStorerAddress;
791-
// Check bytecode of the BytecodeStorer contract is the same as the one in the genesis
792-
expect(bytecodeStorer.bytecode).to.equal(bytecodeStorerDeployedBytecode);
770+
771+
genesisInfo.push({
772+
contractName: GENESIS_CONTRACT_NAMES.BYTECODE_STORER,
773+
genesisObject: bytecodeStorer,
774+
address: bytecodeStorerAddress,
775+
deployedInside: true,
776+
});
777+
778+
if (bytecodeStorer) {
779+
expect(bytecodeStorer.bytecode).to.equal(await ethers.provider.getCode(bytecodeStorerAddress));
793780
}
794781

795782
/// ////////////////////////////////
796783
/// TOKEN WRAPPED IMPL ///////////
797784
/// ///////////////////////////////
798785
logger.info('Updating TokenWrappedBridgeUpgradeable implementation in genesis file...');
799-
const tokenWrapped = newGenesis.genesis.find(function (obj) {
786+
const tokenWrapped = _genesisBase.genesis.find(function (obj) {
800787
return obj.contractName === GENESIS_CONTRACT_NAMES.TOKEN_WRAPPED_IMPLEMENTATION;
801788
});
802-
const tokenWrappedDeployedBytecode = await ethers.provider.getCode(tokenWrappedAddress);
803-
// If its not contained add it to the genesis
804-
if (typeof tokenWrapped === 'undefined') {
805-
const tokenWrappedGenesis = {
806-
contractName: GENESIS_CONTRACT_NAMES.TOKEN_WRAPPED_IMPLEMENTATION,
807-
balance: '0',
808-
nonce: '1',
809-
address: tokenWrappedAddress,
810-
bytecode: tokenWrappedDeployedBytecode,
811-
};
812-
tokenWrappedGenesis.storage = storageModifications.TokenWrappedBridgeUpgradeable_Implementation;
813-
newGenesis.genesis.push(tokenWrappedGenesis);
814-
} else {
815-
// Check bytecode of the TokenWrapped contract is the same as the one in the genesis
816-
expect(tokenWrapped.bytecode).to.equal(tokenWrappedDeployedBytecode);
817-
// Update the address and storage
818-
tokenWrapped.address = tokenWrappedAddress;
789+
790+
genesisInfo.push({
791+
contractName: GENESIS_CONTRACT_NAMES.TOKEN_WRAPPED_IMPLEMENTATION,
792+
genesisObject: tokenWrapped,
793+
address: tokenWrappedAddress,
794+
storage: storageModifications.TokenWrappedBridgeUpgradeable_Implementation,
795+
deployedInside: true,
796+
});
797+
798+
if (tokenWrapped) {
799+
expect(tokenWrapped.bytecode).to.equal(await ethers.provider.getCode(tokenWrappedAddress));
819800
}
820801

821802
/// ///////////////////////////////
@@ -824,33 +805,28 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
824805
logger.info('Updating TokenWrappedBridgeUpgradeable proxy in genesis file...');
825806
// If bridge initialized with a zero sovereign weth address and a non zero gas token, we should add created erc20 weth contract implementation and proxy to the genesis
826807
let wethAddress;
827-
const WETHProxyContractName = GENESIS_CONTRACT_NAMES.WETH_PROXY;
828808
if (
829809
gasTokenAddress !== ethers.ZeroAddress &&
830810
ethers.isAddress(gasTokenAddress) &&
831811
(sovereignWETHAddress === ethers.ZeroAddress || !ethers.isAddress(sovereignWETHAddress))
832812
) {
833-
// Add proxy
834-
wethAddress = `0x${bridgeL2SovereignChain.storage[
813+
wethAddress = `0x${storageModifications.BridgeL2SovereignChain_Initialization[
835814
'0x000000000000000000000000000000000000000000000000000000000000006f'
836815
].slice(26)}`;
837-
const wethGenesisProxy = {
838-
contractName: WETHProxyContractName,
839-
balance: '0',
840-
nonce: '1',
816+
817+
// Add WETH
818+
genesisInfo.push({
819+
contractName: GENESIS_CONTRACT_NAMES.WETH_PROXY,
841820
address: wethAddress,
842-
bytecode: await ethers.provider.getCode(wethAddress),
843-
storage: {
844-
...storageModifications.TokenWrappedBridgeUpgradeable,
845-
...storageModifications.TokenWrappedBridgeUpgradeable_Initialization,
846-
},
847-
};
848-
newGenesis.genesis.push(wethGenesisProxy);
821+
storage: storageModifications.TokenWrappedBridgeUpgradeable,
822+
deployedInside: true,
823+
});
849824

850825
// Check implementation
851826
// eslint-disable-next-line @typescript-eslint/naming-convention
852827
const _IMPLEMENTATION_SLOT = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc';
853-
const wethGenesisImplementationAddress = wethGenesisProxy.storage[_IMPLEMENTATION_SLOT];
828+
const wethGenesisImplementationAddress =
829+
storageModifications.TokenWrappedBridgeUpgradeable[_IMPLEMENTATION_SLOT];
854830
expect(wethGenesisImplementationAddress.slice(26).toLocaleLowerCase()).to.equal(
855831
tokenWrappedAddress.toLocaleLowerCase().slice(2),
856832
);
@@ -862,41 +838,36 @@ export async function createGenesisHardhat(_genesisBase: any, initializeParams:
862838
/// AGGORACLE IMPL //////////////
863839
/// //////////////////////////////
864840
logger.info('Updating AggOracleCommittee implementation in genesis file...');
865-
const aggOracleImplDeployedBytecode = await ethers.provider.getCode(aggOracleImplementationAddress);
866-
// If its not contained add it to the genesis
867-
const aggOracleImpl = {
841+
genesisInfo.push({
868842
contractName: GENESIS_CONTRACT_NAMES.AGGORACLE_COMMITTEE_IMPLEMENTATION,
869-
balance: '0',
870-
nonce: '1',
871843
address: aggOracleImplementationAddress,
872-
bytecode: aggOracleImplDeployedBytecode,
873844
storage: storageModifications.AggOracleCommittee_Implementation,
874-
};
875-
newGenesis.genesis.push(aggOracleImpl);
845+
deployedInside: true,
846+
});
876847

877848
/// ///////////////////////////////
878849
/// AGGORACLE PROXY //////////////
879850
/// ///////////////////////////////
880851
logger.info('Updating AggOracleCommittee proxy in genesis file...');
881-
882-
const aggOracleProxy = {
852+
genesisInfo.push({
883853
contractName: GENESIS_CONTRACT_NAMES.AGGORACLE_COMMITTEE_PROXY,
884-
balance: '0',
885-
nonce: '1',
886-
address: aggOracleCommitteeContract.target,
887-
bytecode: await ethers.provider.getCode(aggOracleCommitteeContract.target),
854+
address: aggOracleCommitteeAddress,
888855
storage: storageModifications.AggOracleCommittee,
889-
};
890-
newGenesis.genesis.push(aggOracleProxy);
856+
deployedInside: true,
857+
});
858+
891859
// Check implementation
892860
// eslint-disable-next-line @typescript-eslint/naming-convention
893861
const _IMPLEMENTATION_SLOT = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc';
894-
const aggOracleCommitteeImplementationAddress = aggOracleProxy.storage[_IMPLEMENTATION_SLOT];
862+
const aggOracleCommitteeImplementationAddress = storageModifications.AggOracleCommittee[_IMPLEMENTATION_SLOT];
895863
expect(aggOracleCommitteeImplementationAddress.slice(26).toLocaleLowerCase()).to.equal(
896864
aggOracleImplementationAddress.toLocaleLowerCase().slice(2),
897865
);
898866
}
899867

868+
const newGenesis = _genesisBase;
869+
await buildGenesis(newGenesis.genesis, genesisInfo);
870+
900871
// switch network previous network
901872
await hre.switchNetwork(previousNetwork);
902873

src/genesis-hardhat/utils.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-await-in-loop */
12
import { ethers, upgrades } from 'hardhat';
23
import { SUPPORTED_BRIDGE_CONTRACTS, SUPPORTED_BRIDGE_CONTRACTS_PROXY, GENESIS_CONTRACT_NAMES } from './constants';
34
import { STORAGE_GENESIS } from './storage';
@@ -358,7 +359,11 @@ export function getStorageTimelockAdminRoleMember(timelockAddress) {
358359
* @param {String} timelockContractAddress - address of the timelock contract
359360
* @returns {Object} - expected storage of the timelock contract
360361
*/
361-
export function getExpectedStoragePolygonZkEVMTimelock(minDelay, timelockContractAddressGenesis, timelockContractAddress) {
362+
export function getExpectedStoragePolygonZkEVMTimelock(
363+
minDelay,
364+
timelockContractAddressGenesis,
365+
timelockContractAddress,
366+
) {
362367
const timelockAdminRole = ethers.keccak256(ethers.toUtf8Bytes('TIMELOCK_ADMIN_ROLE'));
363368
const storageTimelockAdminRoleMemberGenesis = getStorageTimelockAdminRoleMember(timelockContractAddressGenesis);
364369
const storageTimelockAdminRoleMember = getStorageTimelockAdminRoleMember(timelockContractAddress);
@@ -468,6 +473,42 @@ export async function getActualStorage(modificationsStorage, address) {
468473
return actualStorage;
469474
}
470475

476+
/**
477+
* Function to build a new genesis object using genesisInfo
478+
* @param newGenesis genesisBase object, to which new information will be added
479+
* @param genesisInfo Object containing all the information required to update newGenesis
480+
* { contractName, address, storage, genesisObject, deployedInside }
481+
*/
482+
export async function buildGenesis(newGenesis, genesisInfo) {
483+
for (let i = 0; i < genesisInfo.length; i++) {
484+
const info = genesisInfo[i];
485+
if (info.genesisObject && !info.deployedInside) {
486+
// Update the contract name, bytecode, storage and nonce
487+
// Address is not modified because it must match the L1 address
488+
info.genesisObject.contractName = info.contractName;
489+
info.genesisObject.storage = info.storage;
490+
info.genesisObject.bytecode = await ethers.provider.getCode(info.address);
491+
info.genesisObject.nonce = await ethers.provider.getTransactionCount(info.address);
492+
} else if (!info.genesisObject && info.deployedInside) {
493+
// Add a new contract that has been deployed and did not exist in the genesis
494+
const contractGenesis = {
495+
contractName: info.contractName,
496+
balance: '0',
497+
nonce: '1',
498+
address: info.address,
499+
bytecode: await ethers.provider.getCode(info.address),
500+
};
501+
if (info.storage) {
502+
contractGenesis.storage = info.storage;
503+
}
504+
newGenesis.push(contractGenesis);
505+
} else if (info.genesisObject && info.deployedInside) {
506+
// Update contract that has been deployed and exists in the genesis
507+
info.genesisObject.address = info.address;
508+
}
509+
}
510+
}
511+
471512
/**
472513
* Check if two objects are deeply equal
473514
* @param {Object} a - first object

src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export async function getStorageWrites(trace, addressInfo) {
159159
const end = start + size * 2;
160160
const initCodeHex = `0x${memHex.slice(start, end)}`;
161161
const initCodeHash = ethers.solidityPackedKeccak256(['bytes'], [initCodeHex]);
162-
const calculatedAddress = await ethers.getCreate2Address(actualAddress, salt, initCodeHash);
162+
const calculatedAddress = ethers.getCreate2Address(actualAddress, salt, initCodeHash);
163163
// Add new address and nonce
164164
addresses[calculatedAddress] = 1;
165165
// Update nonce actual address

0 commit comments

Comments
 (0)