Skip to content

Commit

Permalink
fix: remove abi folder in e2e tests + update genesis generator docker…
Browse files Browse the repository at this point in the history
… image + clean unused functions
  • Loading branch information
VGau committed Oct 25, 2024
1 parent e8769e1 commit f7c3ef1
Show file tree
Hide file tree
Showing 20 changed files with 94 additions and 6,250 deletions.
71 changes: 12 additions & 59 deletions contracts/common/helpers/deployments.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { ContractFactory, Overrides, Wallet, ethers } from "ethers";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { GetContractTypeFromFactory } from "../../typechain-types/common";
import { ProxyAdmin, ProxyAdmin__factory, TransparentUpgradeableProxy__factory } from "../../typechain-types";
import { AbstractSigner, BytesLike, ethers, Interface, InterfaceAbi } from "ethers";

export function getInitializerData(
contractInterface: ethers.Interface,
initializerFunctionName: string,
args: unknown[],
) {
export function getInitializerData(contractAbi: InterfaceAbi, initializerFunctionName: string, args: unknown[]) {
const contractInterface = new Interface(contractAbi);
const fragment = contractInterface.getFunction(initializerFunctionName);

if (!fragment) {
Expand All @@ -17,55 +11,14 @@ export function getInitializerData(
return contractInterface.encodeFunctionData(fragment, args);
}

export const deployContract = async <TFactory extends ContractFactory>(
contractFactory: TFactory,
deployer: Wallet | HardhatEthersSigner,
export async function deployContractFromArtifacts(
abi: Interface | InterfaceAbi,
bytecode: BytesLike,
wallet: AbstractSigner,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args?: any[],
overrides: Overrides = {},
): Promise<GetContractTypeFromFactory<TFactory>> => {
const deploymentArgs = args || [];
const instance = await contractFactory.connect(deployer).deploy(...deploymentArgs, overrides);
return instance.waitForDeployment() as GetContractTypeFromFactory<TFactory>;
};

export const deployUpgradableContract = async <TFactory extends ContractFactory>(
contractFactory: TFactory,
deployer: Wallet | HardhatEthersSigner,
admin: ProxyAdmin,
initializerData = "0x",
overrides: Overrides = {},
): Promise<GetContractTypeFromFactory<TFactory>> => {
const instance = await deployContract(contractFactory, deployer, [], overrides);

const proxy = await deployContract(new TransparentUpgradeableProxy__factory(), deployer, [
await instance.getAddress(),
await admin.getAddress(),
initializerData,
]);

return proxy as GetContractTypeFromFactory<TFactory>;
};

export async function deployUpgradableContractWithProxyAdmin<TFactory extends ContractFactory>(
contractFactory: TFactory,
deployer: Wallet | HardhatEthersSigner,
initializer?: {
functionName: string;
args: unknown[];
},
overrides: Overrides = {},
): Promise<GetContractTypeFromFactory<TFactory>> {
const proxyFactory = new ProxyAdmin__factory(deployer);

const proxyAdmin = await deployContract(proxyFactory, deployer, [], overrides);

let contract: GetContractTypeFromFactory<TFactory>;
if (initializer) {
const initializerData = getInitializerData(contractFactory.interface, initializer.functionName, initializer.args);
contract = await deployUpgradableContract(contractFactory, deployer, proxyAdmin, initializerData, overrides);
} else {
contract = await deployUpgradableContract(contractFactory, deployer, proxyAdmin, "0x", overrides);
}
return contract;
...args: ethers.ContractMethodArgs<any[]>
) {
const factory = new ethers.ContractFactory(abi, bytecode, wallet);
const contract = await factory.deploy(...args);
return await contract.waitForDeployment();
}
64 changes: 26 additions & 38 deletions contracts/local-deployments-artifacts/deployL2MessageService.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ContractFactory, ethers } from "ethers";
import { ethers } from "ethers";
import * as dotenv from "dotenv";
import {
abi as L2MessageServiceAbi,
bytecode as L2MessageServiceBytecode,
} from "./shared-artifacts/L2MessageService.json";
} from "./dynamic-artifacts/L2MessageService.json";
import { abi as ProxyAdminAbi, bytecode as ProxyAdminBytecode } from "./static-artifacts/ProxyAdmin.json";
import {
abi as TransparentUpgradeableProxyAbi,
Expand All @@ -17,22 +17,10 @@ import {
L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES,
} from "../common/constants";
import { generateRoleAssignments } from "../common/helpers/roles";
import { deployContractFromArtifacts, getInitializerData } from "../common/helpers/deployments";

dotenv.config();

async function deployContract(
abi: ethers.Interface | ethers.InterfaceAbi,
bytecode: ethers.BytesLike,
wallet: ethers.ContractRunner,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...args: ethers.ContractMethodArgs<any[]>
) {
const factory = new ethers.ContractFactory(abi, bytecode, wallet);
const contract = await factory.deploy(...args);
await contract.waitForDeployment();
return contract.getAddress();
}

async function main() {
const messageServiceName = process.env.MESSAGE_SERVICE_CONTRACT_NAME;

Expand All @@ -44,15 +32,17 @@ async function main() {
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const walletNonce = await wallet.getNonce();

// Deploy the implementation contract
const [implementationAddress, proxyAdminAddress] = await Promise.all([
deployContract(L2MessageServiceAbi, L2MessageServiceBytecode, wallet, { nonce: walletNonce }),
deployContract(ProxyAdminAbi, ProxyAdminBytecode, wallet, { nonce: walletNonce + 1 }),
const [l2MessageServiceImplementation, proxyAdmin] = await Promise.all([
deployContractFromArtifacts(L2MessageServiceAbi, L2MessageServiceBytecode, wallet, { nonce: walletNonce }),
deployContractFromArtifacts(ProxyAdminAbi, ProxyAdminBytecode, wallet, { nonce: walletNonce + 1 }),
]);

// Deploy the proxy admin contract
console.log(`Proxy admin contract deployed at ${proxyAdminAddress}`);
console.log(`${messageServiceName} Implementation contract deployed at ${implementationAddress}`);
const proxyAdminAddress = await proxyAdmin.getAddress();
const l2MessageServiceImplementationAddress = await l2MessageServiceImplementation.getAddress();

console.log(
`L2 ProxyAdmin deployed: address=${proxyAdminAddress} blockNumber=${(await proxyAdmin.deploymentTransaction()?.wait())?.blockNumber}`,
);

const pauseTypeRoles = getEnvVarOrDefault("L2MSGSERVICE_PAUSE_TYPE_ROLES", L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES);
const unpauseTypeRoles = getEnvVarOrDefault(
Expand All @@ -66,29 +56,27 @@ async function main() {
);
const roleAddresses = getEnvVarOrDefault("L2MSGSERVICE_ROLE_ADDRESSES", defaultRoleAddresses);
// Prepare the initializer data
const initializer = new ContractFactory(L2MessageServiceAbi, L2MessageServiceBytecode).interface.encodeFunctionData(
"initialize",
[
process.env.L2MSGSERVICE_RATE_LIMIT_PERIOD,
process.env.L2MSGSERVICE_RATE_LIMIT_AMOUNT,
process.env.L2MSGSERVICE_SECURITY_COUNCIL,
roleAddresses,
pauseTypeRoles,
unpauseTypeRoles,
],
);

// Deploy the proxy contract
const initializer = getInitializerData(L2MessageServiceAbi, "initialize", [
process.env.L2MSGSERVICE_RATE_LIMIT_PERIOD,
process.env.L2MSGSERVICE_RATE_LIMIT_AMOUNT,
process.env.L2MSGSERVICE_SECURITY_COUNCIL,
roleAddresses,
pauseTypeRoles,
unpauseTypeRoles,
]);

const proxyAddress = await deployContract(
const proxyContract = await deployContractFromArtifacts(
TransparentUpgradeableProxyAbi,
TransparentUpgradeableProxyBytecode,
wallet,
implementationAddress,
l2MessageServiceImplementationAddress,
proxyAdminAddress,
initializer,
);
console.log(`${messageServiceName} Proxy contract deployed at ${proxyAddress}`);

console.log(
`${messageServiceName} deployed: address=${await proxyContract.getAddress()} blockNumber=${(await proxyContract.deploymentTransaction()?.wait())?.blockNumber}`,
);
}

main().catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { ContractFactory, ethers } from "ethers";
import { ethers } from "ethers";
import fs from "fs";
import path from "path";
import * as dotenv from "dotenv";
import { abi as LineaRollupV5Abi, bytecode as LineaRollupV5Bytecode } from "./dynamic-artifacts/LineaRollupV5.json";
import { abi as ProxyAdminAbi, bytecode as ProxyAdminBytecode } from "./static-artifacts/ProxyAdmin.json";
import {
abi as TransparentUpgradeableProxyAbi,
bytecode as TransparentUpgradeableProxyBytecode,
} from "./static-artifacts/TransparentUpgradeableProxy.json";
import { getRequiredEnvVar } from "../common/helpers/environment";
import { deployContractFromArtifacts, getInitializerData } from "../common/helpers/deployments";

dotenv.config();

function findContractArtifacts(
folderPath: string,
contractName: string,
): { abi: ethers.Interface | ethers.InterfaceAbi; bytecode: ethers.BytesLike } {
): { abi: ethers.InterfaceAbi; bytecode: ethers.BytesLike } {
const files = fs.readdirSync(folderPath);

const foundFile = files.find((file) => file === `${contractName}.json`);
Expand All @@ -33,19 +35,6 @@ function findContractArtifacts(
return parsedContent;
}

async function deployContract(
abi: ethers.Interface | ethers.InterfaceAbi,
bytecode: ethers.BytesLike,
wallet: ethers.ContractRunner,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...args: ethers.ContractMethodArgs<any[]>
) {
const factory = new ethers.ContractFactory(abi, bytecode, wallet);
const contract = await factory.deploy(...args);
await contract.waitForDeployment();
return contract.getAddress();
}

async function main() {
const verifierName = getRequiredEnvVar("VERIFIER_CONTRACT_NAME");
const LineaRollup_initialStateRootHash = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH");
Expand All @@ -57,28 +46,35 @@ async function main() {
const LineaRollup_genesisTimestamp = getRequiredEnvVar("LINEA_ROLLUP_GENESIS_TIMESTAMP");
const lineaRollupName = "LineaRollupV5";

const verifierArtifacts = findContractArtifacts(path.join(__dirname, "./shared-artifacts"), verifierName);
const lineaRollupArtifacts = findContractArtifacts(path.join(__dirname, "./shared-artifacts"), lineaRollupName);
const verifierArtifacts = findContractArtifacts(path.join(__dirname, "./dynamic-artifacts"), verifierName);

const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

const walletNonce = await wallet.getNonce();

const [verifierAddress, lineaRollupImplAddress, proxyAdminAddress] = await Promise.all([
deployContract(verifierArtifacts.abi, verifierArtifacts.bytecode, wallet, { nonce: walletNonce }),
deployContract(lineaRollupArtifacts.abi, lineaRollupArtifacts.bytecode, wallet, { nonce: walletNonce + 1 }),
deployContract(ProxyAdminAbi, ProxyAdminBytecode, wallet, { nonce: walletNonce + 2 }),
const [verifier, lineaRollupImplementation, proxyAdmin] = await Promise.all([
deployContractFromArtifacts(verifierArtifacts.abi, verifierArtifacts.bytecode, wallet, { nonce: walletNonce }),
deployContractFromArtifacts(LineaRollupV5Abi, LineaRollupV5Bytecode, wallet, {
nonce: walletNonce + 1,
}),
deployContractFromArtifacts(ProxyAdminAbi, ProxyAdminBytecode, wallet, { nonce: walletNonce + 2 }),
]);

console.log(`${verifierName} contract deployed at ${verifierAddress}`);
console.log(`${lineaRollupName} Implementation contract deployed at ${lineaRollupImplAddress}`);
console.log(`Proxy admin contract deployed at ${proxyAdminAddress}`);
const [verifierAddress, proxyAdminAddress, lineaRollupImplementationAddress] = await Promise.all([
verifier.getAddress(),
proxyAdmin.getAddress(),
lineaRollupImplementation.getAddress(),
]);

const initializer = new ContractFactory(
lineaRollupArtifacts.abi,
lineaRollupArtifacts.bytecode,
).interface.encodeFunctionData("initialize", [
console.log(
`${verifierName} deployed: address=${verifierAddress} blockNumber=${(await verifier.deploymentTransaction()?.wait())?.blockNumber}`,
);
console.log(
`L1 ProxyAdmin deployed: address=${proxyAdminAddress} blockNumber=${(await proxyAdmin.deploymentTransaction()?.wait())?.blockNumber}`,
);

const initializer = getInitializerData(LineaRollupV5Abi, "initialize", [
LineaRollup_initialStateRootHash,
LineaRollup_initialL2BlockNumber,
verifierAddress,
Expand All @@ -89,16 +85,18 @@ async function main() {
LineaRollup_genesisTimestamp,
]);

const proxyAddress = await deployContract(
const proxyContract = await deployContractFromArtifacts(
TransparentUpgradeableProxyAbi,
TransparentUpgradeableProxyBytecode,
wallet,
lineaRollupImplAddress,
lineaRollupImplementationAddress,
proxyAdminAddress,
initializer,
);

console.log(`${lineaRollupName} Proxy contract deployed at ${proxyAddress}`);
console.log(
`${lineaRollupName} deployed: address=${await proxyContract.getAddress()} blockNumber=${(await proxyContract.deploymentTransaction()?.wait())?.blockNumber}`,
);
}

main().catch((error) => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
17 changes: 6 additions & 11 deletions docker/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -485,21 +485,16 @@ services:
build:
context: ./config/l1-node/
profiles: [ "l1", "debug", "external-to-monorepo" ]
entrypoint:
- /bin/sh
- -c
- |
/config/generate-genesis.sh \
--genesis-time ${L1_GENESIS_TIME} \
--l1-genesis /config/l1-genesis.json \
--network-config /config/network-config.yml \
--mnemonics /config/mnemonics.yaml \
--output-dir /data/l1-node-config
command:
--genesis-time ${L1_GENESIS_TIME}
--l1-genesis /config/l1-genesis.json
--network-config /config/network-config.yml
--mnemonics /config/mnemonics.yaml
--output-dir /data/l1-node-config
volumes:
- ./config/l1-node/cl/network-config.yml:/config/network-config.yml:ro
- ./config/l1-node/cl/mnemonics.yaml:/config/mnemonics.yaml:ro
- ./config/l1-node/el/genesis.json:/config/l1-genesis.json
- ./config/l1-node/generate-genesis.sh:/config/generate-genesis.sh
- local-dev:/data

l1-blockscout:
Expand Down
15 changes: 12 additions & 3 deletions docker/config/l1-node/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
FROM golang:1.22-alpine as builder
FROM golang:1.23-alpine AS builder

RUN apk add --no-cache git && git clone https://github.com/protolambda/eth2-testnet-genesis.git \
&& cd eth2-testnet-genesis \
&& git checkout 4b3498476f14b872b43080eee319adea45286daf \
&& go install .

FROM alpine:3.19.1
WORKDIR /usr/src/app

COPY ./generate-genesis.sh .

FROM alpine:3.20.3

RUN apk add --no-cache bash

WORKDIR /usr/src/app

COPY --from=builder /usr/src/app/generate-genesis.sh .
COPY --from=builder /go/bin/eth2-testnet-genesis /usr/local/bin/

ENTRYPOINT ["/bin/sh", "/usr/src/app/generate-genesis.sh"]

2 changes: 1 addition & 1 deletion e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"test:e2e:local": "TEST_ENV=local npx jest",
"test:e2e:dev": "TEST_ENV=dev npx jest --config ./jest.testnet.config.ts --bail --runInBand --testPathIgnorePatterns=restart.spec.ts",
"test:e2e:sepolia": "TEST_ENV=sepolia npx jest --config ./jest.testnet.config.ts --bail --runInBand --testPathIgnorePatterns=restart.spec.ts",
"postinstall": "typechain --target ethers-v6 --out-dir ./src/typechain './src/abi/*.json'",
"postinstall": "typechain --target ethers-v6 --out-dir ./src/typechain '../contracts/local-deployments-artifacts/**/*.json'",
"lint:fix": "pnpm run lint:ts:fix && pnpm run prettier:fix",
"clean": "rimraf node_modules src/typechain"
},
Expand Down
Loading

0 comments on commit f7c3ef1

Please sign in to comment.