Skip to content

Commit

Permalink
add deployment script for Swellchain (modified copy of Optimism deplo…
Browse files Browse the repository at this point in the history
…yment)
  • Loading branch information
callanbright committed Dec 13, 2024
1 parent d8b68db commit 06160e0
Show file tree
Hide file tree
Showing 16 changed files with 1,625 additions and 2 deletions.
Empty file added .env.wsteth.swe_mainnet
Empty file.
7 changes: 7 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ const config: HardhatUserConfig = {
opt_sepolia_fork: {
url: "http://localhost:9545",
},

swe_mainnet: {
url: env.string("RPC_SWELL_MAINNET", ""),
},
swe_sepolia: {
url: env.string("RPC_SWELL_SEPOLIA", ""),
},
},
gasReporter: {
enabled: env.string("REPORT_GAS", "false") !== "false",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"optimism:test:integration": "hardhat test ./test/optimism/*.integration.test.ts",
"optimism:test:acceptance": "hardhat test ./test/optimism/*.acceptance.test.ts",
"optimism:test:executor": "hardhat test ./test/bridge-executor/optimism.integration.test.ts",
"optimism:test:launch": "REVERT=false hardhat test ./test/optimism/{_launch.test.ts,bridging.integration.test.ts}"
"optimism:test:launch": "REVERT=false hardhat test ./test/optimism/{_launch.test.ts,bridging.integration.test.ts}",
"swellchain:deploy": "ts-node --files ./scripts/swellchain/deploy-bridge.ts"
},
"keywords": [],
"author": "",
Expand Down
80 changes: 80 additions & 0 deletions scripts/swellchain/deploy-bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import env from "../../utils/env";
import prompt from "../../utils/prompt";
import network from "../../utils/network";
import deployment from "../../utils/deployment";
import { BridgingManagement } from "../../utils/bridging-management";
import swellchain from "../../utils/swellchain";


async function main() {
const networkName = env.network();
const ethOptNetwork = network.multichain(["eth", "swe"], networkName);

const [ethDeployer] = ethOptNetwork.getSigners(env.privateKey(), {
forking: env.forking(),
});
const [, sweDeployer] = ethOptNetwork.getSigners(
env.string("SWE_DEPLOYER_PRIVATE_KEY"),
{
forking: env.forking(),
}
);

const deploymentConfig = deployment.loadMultiChainDeploymentConfig();

const [l1DeployScript, l2DeployScript] = await swellchain
.deployment(networkName, { logger: console })
.erc20TokenBridgeDeployScript(
deploymentConfig.token,
{
deployer: ethDeployer,
admins: {
proxy: deploymentConfig.l1.proxyAdmin,
bridge: ethDeployer.address,
},
},
{
deployer: sweDeployer,
admins: {
proxy: deploymentConfig.l2.proxyAdmin,
bridge: sweDeployer.address,
},
}
);

await deployment.printMultiChainDeploymentConfig(
"Deploy Swellchain Bridge",
ethDeployer,
sweDeployer,
deploymentConfig,
l1DeployScript,
l2DeployScript
);

await prompt.proceed();

await l1DeployScript.run();
await l2DeployScript.run();

const l1ERC20TokenBridgeProxyDeployStepIndex = 1;
const l1BridgingManagement = new BridgingManagement(
l1DeployScript.getContractAddress(l1ERC20TokenBridgeProxyDeployStepIndex),
ethDeployer,
{ logger: console }
);

const l2ERC20TokenBridgeProxyDeployStepIndex = 3;
const l2BridgingManagement = new BridgingManagement(
l2DeployScript.getContractAddress(l2ERC20TokenBridgeProxyDeployStepIndex),
sweDeployer,
{ logger: console }
);

await l1BridgingManagement.setup(deploymentConfig.l1);
await l2BridgingManagement.setup(deploymentConfig.l2);
}

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
34 changes: 34 additions & 0 deletions scripts/swellchain/finalize-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CrossChainMessenger, MessageStatus } from "@eth-optimism/sdk";
import env from "../../utils/env";
import network from "../../utils/network";

async function main() {
const networkName = env.network();
const [l1Signer, l2Signer] = network
.multichain(["eth", "swe"], networkName)
.getSigners(env.privateKey(), { forking: false });

const txHash = env.string("TX_HASH");

const crossDomainMessenger = new CrossChainMessenger({
l1ChainId: network.chainId("eth", networkName),
l2ChainId: network.chainId("swe", networkName),
l1SignerOrProvider: l1Signer,
l2SignerOrProvider: l2Signer,
});

const status = await crossDomainMessenger.getMessageStatus(txHash);

if (status !== MessageStatus.READY_FOR_RELAY) {
throw new Error(`Invalid tx status: ${status}`);
}

console.log("Finalizing the L2 -> L1 message");
await crossDomainMessenger.finalizeMessage(txHash);
console.log("Message successfully finalized!");
}

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
37 changes: 37 additions & 0 deletions scripts/swellchain/prove-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CrossChainMessenger, MessageStatus } from "@eth-optimism/sdk";
import env from "../../utils/env";
import network from "../../utils/network";

async function main() {
const networkName = env.network();
const [l1Signer, l2Signer] = network
.multichain(["eth", "swe"], networkName)
.getSigners(env.privateKey(), { forking: false });

const txHash = env.string("TX_HASH");

const crossChainMessenger = new CrossChainMessenger({
l1ChainId: network.chainId("eth", networkName),
l2ChainId: network.chainId("swe", networkName),
l1SignerOrProvider: l1Signer,
l2SignerOrProvider: l2Signer,
bedrock: true,
});

const status = await crossChainMessenger.getMessageStatus(txHash);

if (status !== MessageStatus.READY_TO_PROVE) {
throw new Error(`Invalid tx status: ${status}`);
}

console.log("Prove the L2 -> L1 message");
const tx = await crossChainMessenger.proveMessage(txHash);
console.log(`Waiting for the prove tx ${tx.hash}...`);
await tx.wait();
console.log(`Message was proved successfully!`);
}

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
149 changes: 149 additions & 0 deletions scripts/swellchain/update-ethereum-executor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { assert } from "chai";
import { ethers } from "hardhat";
import { GovBridgeExecutor__factory } from "../../typechain";
import env from "../../utils/env";
import lido from "../../utils/lido";
import network from "../../utils/network";
import swellchain from "../../utils/swellchain";
import prompt from "../../utils/prompt";

// Set address of the bridge executor to run the script
const GOV_BRIDGE_EXECUTOR = "";

async function main() {
const isForking = env.forking();
const networkName = env.network();
const ethSweNetwork = network.multichain(["eth", "swe"], networkName);

const [l1LDOHolder] = ethSweNetwork.getSigners(
env.string("TESTING_SWE_LDO_HOLDER_PRIVATE_KEY"),
{ forking: isForking }
);
const [, sweRunner] = ethSweNetwork.getSigners(env.privateKey(), {
forking: isForking,
});

const govBridgeExecutor = GovBridgeExecutor__factory.connect(
GOV_BRIDGE_EXECUTOR,
sweRunner
);

const newEthExecutorLidoDAO = lido(networkName, l1LDOHolder);
const oldEthExecutorLidoDAO = lido(
networkName === "mainnet" ? "mainnet_test" : networkName,
l1LDOHolder
);
const prevEthGovExecutorAddress =
await govBridgeExecutor.getEthereumGovernanceExecutor();

assert.equal(
oldEthExecutorLidoDAO.agent.address.toLocaleLowerCase(),
prevEthGovExecutorAddress.toLowerCase(),
`${oldEthExecutorLidoDAO.agent.address} is not current ethereumGovernanceExecutor`
);

console.log(` · Is forking: ${isForking}`);
console.log(` · Network Name: ${networkName}`);
console.log(
` · Prev Ethereum Governance Executor: ${prevEthGovExecutorAddress}`
);
console.log(
` · New Ethereum Governance Executor: ${newEthExecutorLidoDAO.agent.address}`
);
console.log(` · LDO Holder: ${l1LDOHolder.address}`);
console.log(` · LDO Holder ETH balance: ${await l1LDOHolder.getBalance()}`);
console.log(` · L2 tx runner: ${sweRunner.address}`);
console.log(` · L2 tx runner ETH balance: ${await sweRunner.getBalance()}`);

await prompt.proceed();

console.log(`Preparing the voting tx...`);

const sweAddresses = swellchain.addresses(networkName);

// Prepare data for Governance Bridge Executor
const executorCalldata = await govBridgeExecutor.interface.encodeFunctionData(
"queue",
[
[GOV_BRIDGE_EXECUTOR],
[0],
["updateEthereumGovernanceExecutor(address)"],
[
ethers.utils.defaultAbiCoder.encode(
["address"],
[newEthExecutorLidoDAO.agent.address]
),
],
[false],
]
);

const { callvalue, calldata } = await swellchain
.messaging(networkName, { forking: isForking })
.prepareL2Message({
calldata: executorCalldata,
recipient: GOV_BRIDGE_EXECUTOR,
sender: oldEthExecutorLidoDAO.agent.address,
});

const createVoteTx = await oldEthExecutorLidoDAO.createVote(
l1LDOHolder,
"Update ethereumGovernanceExecutor on Swellchain Governance Bridge Executor",
{
address: oldEthExecutorLidoDAO.agent.address,
signature: "execute(address,uint256,bytes)",
decodedCallData: [
sweAddresses.L1CrossDomainMessenger,
callvalue,
calldata,
],
}
);

console.log("Creating voting to update ethereumGovernanceExecutor...");
await createVoteTx.wait();
console.log(`Vote was created!`);

const votesCount = await oldEthExecutorLidoDAO.voting.votesLength();
const voteId = votesCount.sub(1);

console.log(`New vote id ${voteId.toString()}`);
console.log(`Voting for and executing the vote...`);

const voteAndExecuteTx = await oldEthExecutorLidoDAO.voteAndExecute(
l1LDOHolder,
voteId,
true
);
const executeTxReceipt = await voteAndExecuteTx.wait();

console.log(`Vote ${voteId.toString()} was executed!`);

console.log(`Waiting for L2 transaction...`);
await swellchain
.messaging(networkName, { forking: isForking })
.waitForL2Message(executeTxReceipt.transactionHash);

console.log(`Message delivered to L2`);

console.log("Executing the queued task...");
// execute task on L2
const tasksCount = await govBridgeExecutor.getActionsSetCount();
const targetTaskId = tasksCount.toNumber() - 1;

const tx = await govBridgeExecutor.execute(targetTaskId);
await tx.wait();
console.log(`Task executed on L2!`);

const ethereumGovernanceExecutor =
await govBridgeExecutor.getEthereumGovernanceExecutor();

console.log(
`New ethereum governance executor is: ${ethereumGovernanceExecutor}`
);
}

main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
17 changes: 16 additions & 1 deletion utils/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { HardhatRuntimeEnvironment, HttpNetworkConfig } from "hardhat/types";

import env from "./env";

type ChainNameShort = "arb" | "opt" | "eth";
type ChainNameShort = "arb" | "opt" | "eth" | "swe";
export type NetworkName = "sepolia" | "mainnet";
export type SignerOrProvider = Signer | Provider;

Expand All @@ -23,6 +23,10 @@ const HARDHAT_NETWORK_NAMES = {
sepolia: "opt_sepolia",
mainnet: "opt_mainnet",
},
swe: {
sepolia: "swe_sepolia",
mainnet: "swe_mainnet",
},
};

const HARDHAT_NETWORK_NAMES_FORK = {
Expand All @@ -38,6 +42,10 @@ const HARDHAT_NETWORK_NAMES_FORK = {
sepolia: "opt_sepolia_fork",
mainnet: "opt_mainnet_fork",
},
swe: {
sepolia: "swe_sepolia_fork",
mainnet: "swe_mainnet_fork",
},
};

export function getConfig(networkName: string, hre: HardhatRuntimeEnvironment) {
Expand Down Expand Up @@ -129,6 +137,10 @@ function getChainId(protocol: ChainNameShort, networkName: NetworkName) {
mainnet: 42161,
sepolia: 421613,
},
swe:{
mainnet: 1923,
sepolia: 1924,
}
};
const chainId = chainIds[protocol][networkName];
if (!chainId) {
Expand All @@ -148,6 +160,9 @@ function getBlockExplorerBaseUrlByChainId(chainId: number) {
// optimism
10: "https://optimistic.etherscan.io",
11155420: "https://blockscout.com/optimism/sepolia",
// swellchain
1923: "https://swell-mainnet.alt.technology",
1924: "https://swell-testnet.alt.technology",
// forked node
31337: "https://etherscan.io",
};
Expand Down
Loading

0 comments on commit 06160e0

Please sign in to comment.