Skip to content

Commit

Permalink
save steps state to files
Browse files Browse the repository at this point in the history
  • Loading branch information
kovalgek committed Jan 28, 2025
1 parent 3325e4f commit 6fa43b9
Show file tree
Hide file tree
Showing 17 changed files with 586 additions and 280 deletions.
1 change: 1 addition & 0 deletions configs/unichain_sepolia.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ parameters:
- &l2EmergencyBreaksMultisig "0xa5F1d7D49F581136Cf6e58B32cBE9a2039C48bA1"
- &l1CrossDomainMessenger "0x448A37330A60494E666F6DD60aD48d930AEbA381"
- &l2CrossDomainMessenger "0x4200000000000000000000000000000000000007"
- &genesisTime 1655733600

statemate:
l1CrossDomainMessenger: *l1CrossDomainMessenger
Expand Down
79 changes: 79 additions & 0 deletions src/block-explorer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { loadDeployedContractsWithArgs } from "./deployment-args";
import { LogCallback, LogType } from "./log-utils";

async function checkAddressesContractStatus({
configWihAddresses,
endpoint,
apiKey,
maxTries = 3,
checkInterval = 1000,
logCallback
}: {
configWihAddresses: string,
endpoint: string,
apiKey: string,
maxTries: number;
checkInterval: number;
logCallback: LogCallback;
}) {
const args = loadDeployedContractsWithArgs(configWihAddresses);
let contract: keyof typeof args;
for (contract in args) {
await checkAddressContractStatus({
address: contract,
endpoint: endpoint,
apiKey: apiKey,
maxTries: maxTries,
checkInterval: checkInterval,
logCallback: logCallback
});
}
}

async function checkAddressContractStatus({
address,
endpoint,
apiKey,
maxTries = 3,
checkInterval = 1000,
logCallback
}: {
address: string;
endpoint: string,
apiKey: string,
maxTries: number;
checkInterval: number;
logCallback: LogCallback;
}) {
logCallback(`Check address ${address} for being contract in block explorer`, LogType.Level1);

for (let tryIndex = 0; tryIndex < maxTries; tryIndex++) {
try {
const query = `${endpoint}?module=contract&action=getsourcecode&address=${address}&apikey=${apiKey}`;
const response = await fetch(query);
const body = await response.json();

if (body.status === "1" && body.result.length > 0) {
const contractInfo = body.result[0];
const isContract = !!(contractInfo.SourceCode || contractInfo.ABI);

if (isContract) {
logCallback(`${address} is identified as a contract.`, LogType.Level1);
return;
}
}

logCallback(`${address} appears to be an EOA. Retrying in ${checkInterval / 1000} seconds...`, LogType.Level1);
await new Promise((resolve) => setTimeout(resolve, checkInterval));
} catch (error) {
logCallback(`Error ${error} checking address ${address}`, LogType.Level1);
await new Promise((resolve) => setTimeout(resolve, checkInterval));
}
}

logCallback(`${address} could not be confirmed as a contract after ${maxTries} attempts.`, LogType.Level1);
}

export {
checkAddressesContractStatus
}
6 changes: 5 additions & 1 deletion src/command-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { spawn } from "child_process";

import { LogCallback, LogType } from "./log-utils";

export async function runCommand({
async function runCommand({
command,
args = [],
workingDirectory = process.cwd(),
Expand Down Expand Up @@ -92,3 +92,7 @@ export async function runCommand({
});
});
}

export {
runCommand
}
93 changes: 67 additions & 26 deletions src/deploy-all-contracts.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { cpSync, readFileSync } from "node:fs";
import { cpSync } from "node:fs";
import process from "node:process";

import dotenv from "dotenv";
import { ethers } from "ethers";

import { runCommand } from "./command-utils";
import { DeployParameters } from "./config";
import { DeploymentArtifacts, loadDeploymentArtifacts, saveDeployArtifacts } from "./deployment-artifacts";
import env from "./env";
import { LogCallback, LogType } from "./log-utils";
import { DeployParameters } from "./main-config";
import { NetworkType } from "./rpc-utils";

const WAIT_TX_TIMEOUT = 30_000;

export async function burnL2DeployerNonces(l2RpcUrl: string, numNonces: number, logCallback: LogCallback) {
async function burnL2DeployerNonces(l2RpcUrl: string, numNonces: number, logCallback: LogCallback) {
const l2Provider = new ethers.JsonRpcProvider(l2RpcUrl);
const l2Deployer = new ethers.Wallet(process.env.DEPLOYER_PRIVATE_KEY!, l2Provider);
const l2DeployerAddress = await l2Deployer.getAddress();
Expand All @@ -35,12 +36,14 @@ export async function burnL2DeployerNonces(l2RpcUrl: string, numNonces: number,
`Burning ${nonceIndex} tx, try num: ${tryNum} maxFeePerGas: ${maxFeePerGas} maxPriorityFeePerGas:${maxPriorityFeePerGas}`,
LogType.Level1,
);
const nonce = await l2Provider.getTransactionCount(l2Deployer.address);
const tx = await waitWithTimeout(
l2Deployer.sendTransaction({
to: l2DeployerAddress,
value: 0,
maxPriorityFeePerGas: maxPriorityFeePerGas * retryGasFactor(tryNum),
maxFeePerGas: (maxFeePerGas + maxPriorityFeePerGas) * retryGasFactor(tryNum),
nonce: nonce,
}),
WAIT_TX_TIMEOUT,
);
Expand Down Expand Up @@ -68,7 +71,7 @@ export async function burnL2DeployerNonces(l2RpcUrl: string, numNonces: number,
}
}

export async function runDeployScript({
async function runDeployScript({
scriptPath,
throwOnFail = true,
tryNumber = 1,
Expand All @@ -94,17 +97,24 @@ export async function runDeployScript({
});
}

export function populateDeployScriptEnvs(
function populateDeployScriptEnvs({
deploymentConfig,
deploymentResultsFilename,
networkType,
}: {
deploymentConfig: DeployParameters,
govBridgeExecutor: string,
deploymentResultsFilename: string,
networkType: NetworkType,
) {
}) {
function formattedArray(configArray: Array<string>) {
return `[${configArray.map((ts: string) => `"${ts.toString()}"`)}]`;
}
const l1Config = deploymentConfig.l1;
const l2Config = deploymentConfig.l2;

const deployedContracts = loadDeploymentArtifacts({fileName: deploymentResultsFilename});
const govBridgeExecutor = deployedContracts.l2.govBridgeExecutor;

dotenv.populate(
process.env as { [key: string]: string },
{
Expand Down Expand Up @@ -182,30 +192,61 @@ export function populateDeployScriptEnvs(
);
}

function copyDeploymentArtifacts(originalDeployFileName: string, deployResultFileName: string) {
const originalDeployFilePath = `./lido-l2-with-steth/${originalDeployFileName}`;
function copyDeploymentArtifacts({
originalDeploymentFileName,
deployResultFileName,
}: {
originalDeploymentFileName: string;
deployResultFileName: string;
}) {
const originalDeployFilePath = `./lido-l2-with-steth/${originalDeploymentFileName}`;
cpSync(originalDeployFilePath, `./artifacts/${deployResultFileName}`);
}

export function copyArtifacts({
deploymentResult,
l1DeploymentArgs,
l2DeploymentArgs,
function copyAndMergeArtifacts({
originalDeploymentFileName,
deploymentResultFileName,
}: {
deploymentResult: string;
l1DeploymentArgs: string;
l2DeploymentArgs: string;
originalDeploymentFileName: string;
deploymentResultFileName: string;
}) {
copyDeploymentArtifacts("deployResult.json", deploymentResult);
copyDeploymentArtifacts("l1DeployArgs.json", l1DeploymentArgs);
copyDeploymentArtifacts("l2DeployArgs.json", l2DeploymentArgs);
const deploymentResultWithoutGovExecutor = loadDeploymentArtifacts({fileName: originalDeploymentFileName, folder: "./lido-l2-with-steth"});
const deploymentResult = loadDeploymentArtifacts({fileName: deploymentResultFileName});
const mappedDeploymentResult = mappedFromOriginalDeploymentArtifacts(deploymentResultWithoutGovExecutor);
mappedDeploymentResult.l2.govBridgeExecutor = deploymentResult["l2"]["govBridgeExecutor"];
saveDeployArtifacts(mappedDeploymentResult, deploymentResultFileName);
}

export function configFromArtifacts(fileName: string) {
const data = readFileSync(`./artifacts/${fileName}`, "utf8");
try {
return JSON.parse(data);
} catch (error) {
throw new Error(`can't parse deploy file ${fileName}: ${(error as Error).message}`);
}
function mappedFromOriginalDeploymentArtifacts(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
originalDeploymentArtifacts: any
): DeploymentArtifacts {
return {
l1: {
bridgeImplAddress: originalDeploymentArtifacts["ethereum"]["bridgeImplAddress"],
bridgeProxyAddress: originalDeploymentArtifacts["ethereum"]["bridgeProxyAddress"],
opStackTokenRatePusherImplAddress: originalDeploymentArtifacts["ethereum"]["opStackTokenRatePusherImplAddress"],
lastBlockNumber: originalDeploymentArtifacts["ethereum"]["lastBlockNumber"],
},
l2: {
govBridgeExecutor: originalDeploymentArtifacts["optimism"]["govBridgeExecutor"],
tokenImplAddress: originalDeploymentArtifacts["optimism"]["tokenImplAddress"],
tokenProxyAddress: originalDeploymentArtifacts["optimism"]["tokenProxyAddress"],
tokenRebasableImplAddress: originalDeploymentArtifacts["optimism"]["tokenRebasableImplAddress"],
tokenRebasableProxyAddress: originalDeploymentArtifacts["optimism"]["tokenRebasableProxyAddress"],
tokenBridgeImplAddress: originalDeploymentArtifacts["optimism"]["tokenBridgeImplAddress"],
tokenBridgeProxyAddress: originalDeploymentArtifacts["optimism"]["tokenBridgeProxyAddress"],
tokenRateOracleImplAddress: originalDeploymentArtifacts["optimism"]["tokenRateOracleImplAddress"],
tokenRateOracleProxyAddress: originalDeploymentArtifacts["optimism"]["tokenRateOracleProxyAddress"],
lastBlockNumber: originalDeploymentArtifacts["optimism"]["lastBlockNumber"],
},
};
}

export {
burnL2DeployerNonces,
runDeployScript,
populateDeployScriptEnvs,
copyDeploymentArtifacts,
copyAndMergeArtifacts
}
48 changes: 27 additions & 21 deletions src/deploy-gov-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { readFileSync, writeFileSync } from "node:fs";

import { ethers } from "ethers";

import { DeployParameters, GovBridgeExecutor } from "./config";
import { loadDeploymentArtifacts, saveDeployArtifacts } from "./deployment-artifacts";
import env from "./env";
import { LogCallback, LogType } from "./log-utils";
import { DeployParameters, GovBridgeExecutor } from "./main-config";

const GOV_BRIDGE_EXECUTOR_PATH =
"./governance-crosschain-bridges/artifacts/contracts/bridges/OptimismBridgeExecutor.sol/OptimismBridgeExecutor.json";
Expand All @@ -20,7 +21,7 @@ type ConstructorArgs = [
string, // ovmGuiardian
];

export async function deployGovExecutor(deploymentConfig: DeployParameters, rpcUrl: string, logCallback: LogCallback) {
async function deployGovExecutor(deploymentConfig: DeployParameters, rpcUrl: string, logCallback: LogCallback) {
const contractJson = JSON.parse(readFileSync(GOV_BRIDGE_EXECUTOR_PATH, "utf-8"));
const { abi, bytecode } = contractJson;
const provider = new ethers.JsonRpcProvider(rpcUrl);
Expand Down Expand Up @@ -68,13 +69,16 @@ async function deploy(
}
}

export function saveGovExecutorDeploymentArgs(
contractAddress: string,
deploymentConfig: DeployParameters,
fileName: string,
) {
function saveGovExecutorDeploymentArgs({
contractAddress,
deploymentConfig,
fileName,
}: {
contractAddress: string;
deploymentConfig: DeployParameters;
fileName: string;
}) {
const govBridgeExecutorConfig = deploymentConfig.l2.govBridgeExecutor;

const content = {
[contractAddress]: [
govBridgeExecutorConfig.ovmL2Messenger,
Expand All @@ -86,21 +90,23 @@ export function saveGovExecutorDeploymentArgs(
govBridgeExecutorConfig.ovmGuiardian,
],
};
// save args
writeFileSync(`./artifacts/${fileName}`, JSON.stringify(content, null, 2));
}

export function addGovExecutorToDeploymentArtifacts(govBridgeExecutor: string, deploymentResultsFilename: string) {
const newContractsConfig = configFromArtifacts(deploymentResultsFilename);
newContractsConfig["optimism"]["govBridgeExecutor"] = govBridgeExecutor;
writeFileSync(`./artifacts/${deploymentResultsFilename}`, JSON.stringify(newContractsConfig, null, 2));
function saveGovExecutorToDeploymentArtifacts({
govBridgeExecutor,
deploymentResultsFilename,
}: {
govBridgeExecutor: string;
deploymentResultsFilename: string;
}) {
const deployArtifacts = loadDeploymentArtifacts({fileName: deploymentResultsFilename});
deployArtifacts.l2.govBridgeExecutor = govBridgeExecutor;
saveDeployArtifacts(deployArtifacts, deploymentResultsFilename);
}

function configFromArtifacts(fileName: string) {
const data = readFileSync(`./artifacts/${fileName}`, "utf8");
try {
return JSON.parse(data);
} catch (error) {
throw new Error(`can't parse deploy file ${fileName}: ${(error as Error).message}`);
}
}
export {
deployGovExecutor,
saveGovExecutorDeploymentArgs,
saveGovExecutorToDeploymentArtifacts
}
14 changes: 14 additions & 0 deletions src/deployment-args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { readFileSync } from "fs";

function loadDeployedContractsWithArgs(fileName: string) {
const data = readFileSync(`./artifacts/${fileName}`, "utf8");
try {
return JSON.parse(data);
} catch (error) {
throw new Error(`can't parse deploy file ${fileName}: ${(error as Error).message}`);
}
}

export {
loadDeployedContractsWithArgs
}
Loading

0 comments on commit 6fa43b9

Please sign in to comment.