Skip to content

Commit 4bdfb72

Browse files
authored
Chore(contract-manager) Executor Contract Type (#2838)
* added EvmExecutorContract.json * temp_list * deploy_evm_executor script * deployed Executor on Ethereum Sepolia * updat * update * update * update * chore(executor)-Deployed Executor on Ethereal Testnet * update
1 parent 9dcec57 commit 4bdfb72

File tree

11 files changed

+466
-47
lines changed

11 files changed

+466
-47
lines changed

contract_manager/scripts/common.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import { Contract } from "web3-eth-contract";
66
import { InferredOptionType } from "yargs";
77
import { PrivateKey, getDefaultDeploymentConfig } from "../src/core/base";
88
import { EvmChain } from "../src/core/chains";
9-
import { EvmEntropyContract, EvmWormholeContract } from "../src/core/contracts";
9+
import {
10+
EvmEntropyContract,
11+
EvmExecutorContract,
12+
EvmWormholeContract,
13+
} from "../src/core/contracts";
1014

1115
export interface BaseDeployConfig {
1216
gasMultiplier: number;
@@ -237,6 +241,27 @@ export function findWormholeContract(
237241
}
238242
}
239243

244+
/**
245+
* Finds the executor contract for a given EVM chain.
246+
* @param {EvmChain} chain The EVM chain to find the executor contract for.
247+
* @returns If found, the executor contract for the given EVM chain. Else, undefined
248+
*/
249+
export function findExecutorContract(
250+
chain: EvmChain,
251+
): EvmExecutorContract | undefined {
252+
for (const contract of Object.values(DefaultStore.executor_contracts)) {
253+
if (
254+
contract instanceof EvmExecutorContract &&
255+
contract.chain.getId() === chain.getId()
256+
) {
257+
console.log(
258+
`Found executor contract for ${chain.getId()} at ${contract.address}`,
259+
);
260+
return contract;
261+
}
262+
}
263+
}
264+
240265
export interface DeployWormholeReceiverContractsConfig
241266
extends BaseDeployConfig {
242267
saveContract: boolean;

contract_manager/scripts/deploy_evm_entropy_contracts.ts

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
} from "../src/core/contracts/evm";
1010
import {
1111
DeploymentType,
12-
getDefaultDeploymentConfig,
1312
toDeploymentType,
1413
toPrivateKey,
1514
} from "../src/core/base";
@@ -22,6 +21,7 @@ import {
2221
topupAccountsIfNecessary,
2322
DefaultAddresses,
2423
} from "./common";
24+
import { getOrDeployExecutorContract } from "./deploy_evm_executor";
2525

2626
interface DeploymentConfig extends BaseDeployConfig {
2727
type: DeploymentType;
@@ -44,44 +44,6 @@ const parser = yargs(hideBin(process.argv))
4444
},
4545
});
4646

47-
async function deployExecutorContracts(
48-
chain: EvmChain,
49-
config: DeploymentConfig,
50-
wormholeAddr: string,
51-
): Promise<string> {
52-
const executorImplAddr = await deployIfNotCached(
53-
CACHE_FILE,
54-
chain,
55-
config,
56-
"ExecutorUpgradable",
57-
[],
58-
);
59-
60-
// Craft the init data for the proxy contract
61-
const { governanceDataSource } = getDefaultDeploymentConfig(config.type);
62-
63-
const executorImplContract = getWeb3Contract(
64-
config.jsonOutputDir,
65-
"ExecutorUpgradable",
66-
executorImplAddr,
67-
);
68-
69-
const executorInitData = executorImplContract.methods
70-
.initialize(
71-
wormholeAddr,
72-
0, // lastExecutedSequence,
73-
chain.getWormholeChainId(),
74-
governanceDataSource.emitterChain,
75-
`0x${governanceDataSource.emitterAddress}`,
76-
)
77-
.encodeABI();
78-
79-
return await deployIfNotCached(CACHE_FILE, chain, config, "ERC1967Proxy", [
80-
executorImplAddr,
81-
executorInitData,
82-
]);
83-
}
84-
8547
async function deployEntropyContracts(
8648
chain: EvmChain,
8749
config: DeploymentConfig,
@@ -166,15 +128,15 @@ async function main() {
166128

167129
console.log(`Deploying entropy contracts on ${chain.getId()}...`);
168130

169-
const executorAddr = await deployExecutorContracts(
131+
const executorContract = await getOrDeployExecutorContract(
170132
chain,
171133
deploymentConfig,
172134
wormholeContract.address,
173135
);
174136
const entropyAddr = await deployEntropyContracts(
175137
chain,
176138
deploymentConfig,
177-
executorAddr,
139+
executorContract.address,
178140
);
179141

180142
if (deploymentConfig.saveContract) {
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import yargs from "yargs";
2+
import { hideBin } from "yargs/helpers";
3+
import { EvmChain } from "../src/core/chains";
4+
import {
5+
BaseDeployConfig,
6+
COMMON_DEPLOY_OPTIONS,
7+
deployIfNotCached,
8+
findExecutorContract,
9+
getOrDeployWormholeContract,
10+
getWeb3Contract,
11+
} from "./common";
12+
import {
13+
DeploymentType,
14+
getDefaultDeploymentConfig,
15+
toDeploymentType,
16+
toPrivateKey,
17+
} from "../src/core/base";
18+
import { DefaultStore } from "../src/node/utils/store";
19+
import { EvmExecutorContract } from "../src/core/contracts/evm";
20+
21+
const CACHE_FILE = ".cache-deploy-evm-executor";
22+
23+
const parser = yargs(hideBin(process.argv))
24+
.scriptName("deploy_evm_executor.ts")
25+
.usage(
26+
"Usage: $0 --std-output-dir <path/to/std-output-dir/> --private-key <private-key> --chain <chain>",
27+
)
28+
.options({
29+
...COMMON_DEPLOY_OPTIONS,
30+
chain: {
31+
type: "string",
32+
demandOption: true,
33+
desc: "Chain to upload the contract on. Can be one of the evm chains available in the store",
34+
},
35+
});
36+
37+
interface DeploymentConfig extends BaseDeployConfig {
38+
type: DeploymentType;
39+
saveContract: boolean;
40+
}
41+
42+
export async function getOrDeployExecutorContract(
43+
chain: EvmChain,
44+
config: DeploymentConfig,
45+
wormholeAddr: string,
46+
): Promise<EvmExecutorContract> {
47+
return (
48+
findExecutorContract(chain) ??
49+
(await deployExecutorContracts(chain, config, wormholeAddr))
50+
);
51+
}
52+
53+
/**
54+
* Deploys the executor contracts for a given EVM chain.
55+
* @param {EvmChain} chain The EVM chain to deploy the executor contracts for.
56+
* @param {DeploymentConfig} config The deployment configuration.
57+
* @param {string} wormholeAddr The address of the wormhole contract.
58+
* @returns {Promise<string>} The address of the deployed executor contract.
59+
*/
60+
export async function deployExecutorContracts(
61+
chain: EvmChain,
62+
config: DeploymentConfig,
63+
wormholeAddr: string,
64+
): Promise<EvmExecutorContract> {
65+
const executorImplAddr = await deployIfNotCached(
66+
CACHE_FILE,
67+
chain,
68+
config,
69+
"ExecutorUpgradable",
70+
[],
71+
);
72+
73+
// Craft the init data for the proxy contract
74+
const { governanceDataSource } = getDefaultDeploymentConfig(config.type);
75+
76+
const executorImplContract = getWeb3Contract(
77+
config.jsonOutputDir,
78+
"ExecutorUpgradable",
79+
executorImplAddr,
80+
);
81+
82+
const executorInitData = executorImplContract.methods
83+
.initialize(
84+
wormholeAddr,
85+
0, // lastExecutedSequence,
86+
chain.getWormholeChainId(),
87+
governanceDataSource.emitterChain,
88+
`0x${governanceDataSource.emitterAddress}`,
89+
)
90+
.encodeABI();
91+
92+
const executorAddr = await deployIfNotCached(
93+
CACHE_FILE,
94+
chain,
95+
config,
96+
"ERC1967Proxy",
97+
[executorImplAddr, executorInitData],
98+
);
99+
100+
return new EvmExecutorContract(chain, executorAddr);
101+
}
102+
103+
export async function main() {
104+
const argv = await parser.argv;
105+
106+
const chain = DefaultStore.getChainOrThrow(argv.chain, EvmChain);
107+
108+
const deploymentConfig: DeploymentConfig = {
109+
type: toDeploymentType(argv.deploymentType),
110+
gasMultiplier: argv.gasMultiplier,
111+
gasPriceMultiplier: argv.gasPriceMultiplier,
112+
privateKey: toPrivateKey(argv.privateKey),
113+
jsonOutputDir: argv.stdOutputDir,
114+
saveContract: argv.saveContract,
115+
};
116+
117+
const wormholeContract = await getOrDeployWormholeContract(
118+
chain,
119+
deploymentConfig,
120+
CACHE_FILE,
121+
);
122+
123+
console.log(
124+
`Deployment config: ${JSON.stringify(deploymentConfig, null, 2)}\n`,
125+
);
126+
127+
console.log(`Deploying executor contracts on ${chain.getId()}...`);
128+
129+
const executorContract = await getOrDeployExecutorContract(
130+
chain,
131+
deploymentConfig,
132+
wormholeContract.address,
133+
);
134+
135+
if (deploymentConfig.saveContract) {
136+
console.log("Saving the contract in the store...");
137+
DefaultStore.executor_contracts[executorContract.getId()] =
138+
executorContract;
139+
DefaultStore.saveAllContracts();
140+
}
141+
142+
console.log(
143+
`✅ Executor contract on ${chain.getId()} at ${executorContract.address}\n\n`,
144+
);
145+
}
146+
147+
main();

contract_manager/src/core/contracts/evm.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,16 +412,32 @@ export class EvmEntropyContract extends Storable {
412412
}
413413
}
414414

415-
export class EvmExecutorContract {
415+
export class EvmExecutorContract extends Storable {
416+
static type = "EvmExecutorContract";
417+
416418
constructor(
417419
public chain: EvmChain,
418420
public address: string,
419-
) {}
421+
) {
422+
super();
423+
}
420424

421425
getId(): string {
422426
return `${this.chain.getId()}_${this.address}`;
423427
}
424428

429+
getType(): string {
430+
return EvmExecutorContract.type;
431+
}
432+
433+
toJson() {
434+
return {
435+
chain: this.chain.getId(),
436+
address: this.address,
437+
type: EvmExecutorContract.type,
438+
};
439+
}
440+
425441
async getWormholeContract(): Promise<EvmWormholeContract> {
426442
const web3 = this.chain.getWeb3();
427443
//Unfortunately, there is no public method to get the wormhole address
@@ -431,6 +447,17 @@ export class EvmExecutorContract {
431447
return new EvmWormholeContract(this.chain, address);
432448
}
433449

450+
static fromJson(
451+
chain: Chain,
452+
parsed: { type: string; address: string },
453+
): EvmExecutorContract {
454+
if (parsed.type !== EvmExecutorContract.type)
455+
throw new Error("Invalid type");
456+
if (!(chain instanceof EvmChain))
457+
throw new Error(`Wrong chain type ${chain}`);
458+
return new EvmExecutorContract(chain, parsed.address);
459+
}
460+
434461
getContract() {
435462
const web3 = this.chain.getWeb3();
436463
return new web3.eth.Contract(EXECUTOR_ABI, this.address);

contract_manager/src/node/utils/store.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
IotaWormholeContract,
3030
IotaPriceFeedContract,
3131
EvmPulseContract,
32+
EvmExecutorContract,
3233
} from "../../core/contracts";
3334
import { Token } from "../../core/token";
3435
import { PriceFeedContract, Storable } from "../../core/base";
@@ -46,6 +47,7 @@ import {
4647
export class Store {
4748
public chains: Record<string, Chain> = { global: new GlobalChain() };
4849
public contracts: Record<string, PriceFeedContract> = {};
50+
public executor_contracts: Record<string, EvmExecutorContract> = {};
4951
public entropy_contracts: Record<string, EvmEntropyContract> = {};
5052
public pulse_contracts: Record<string, EvmPulseContract> = {};
5153
public wormhole_contracts: Record<string, WormholeContract> = {};
@@ -118,6 +120,7 @@ export class Store {
118120
const contracts: Storable[] = Object.values(this.contracts);
119121
contracts.push(...Object.values(this.entropy_contracts));
120122
contracts.push(...Object.values(this.wormhole_contracts));
123+
contracts.push(...Object.values(this.executor_contracts));
121124
for (const contract of contracts) {
122125
if (!contractsByType[contract.getType()]) {
123126
contractsByType[contract.getType()] = [];
@@ -167,6 +170,7 @@ export class Store {
167170
[AptosWormholeContract.type]: AptosWormholeContract,
168171
[EvmEntropyContract.type]: EvmEntropyContract,
169172
[EvmWormholeContract.type]: EvmWormholeContract,
173+
[EvmExecutorContract.type]: EvmExecutorContract,
170174
[FuelPriceFeedContract.type]: FuelPriceFeedContract,
171175
[FuelWormholeContract.type]: FuelWormholeContract,
172176
[StarknetPriceFeedContract.type]: StarknetPriceFeedContract,
@@ -192,7 +196,8 @@ export class Store {
192196
if (
193197
this.contracts[chainContract.getId()] ||
194198
this.entropy_contracts[chainContract.getId()] ||
195-
this.wormhole_contracts[chainContract.getId()]
199+
this.wormhole_contracts[chainContract.getId()] ||
200+
this.executor_contracts[chainContract.getId()]
196201
)
197202
throw new Error(
198203
`Multiple contracts with id ${chainContract.getId()} found`,
@@ -201,6 +206,8 @@ export class Store {
201206
this.entropy_contracts[chainContract.getId()] = chainContract;
202207
} else if (chainContract instanceof WormholeContract) {
203208
this.wormhole_contracts[chainContract.getId()] = chainContract;
209+
} else if (chainContract instanceof EvmExecutorContract) {
210+
this.executor_contracts[chainContract.getId()] = chainContract;
204211
} else {
205212
this.contracts[chainContract.getId()] = chainContract;
206213
}

contract_manager/store/chains/EvmChains.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@
401401
{
402402
"id": "sepolia",
403403
"mainnet": false,
404-
"rpcUrl": "https://eth-sepolia.blastapi.io/$ENV_BLAST_API_KEY",
404+
"rpcUrl": "https://eth-sepolia.public.blastapi.io",
405405
"networkId": 11155111,
406406
"type": "EvmChain"
407407
},
@@ -1265,5 +1265,12 @@
12651265
"rpcUrl": "https://k8s.testnet.json-rpc.injective.network/",
12661266
"networkId": 1439,
12671267
"type": "EvmChain"
1268+
},
1269+
{
1270+
"id": "ethereal_testnet",
1271+
"mainnet": false,
1272+
"rpcUrl": "https://rpc-ethereal-testnet.t.conduit.xyz",
1273+
"networkId": 657468,
1274+
"type": "EvmChain"
12681275
}
12691276
]

0 commit comments

Comments
 (0)