[contract_manager] entropy deployment script (#1280)
* entropy deployment * entropy deployment script * remove unused * refactored * requested changes * correct comment
This commit is contained in:
parent
c330e40277
commit
ca852ea989
|
@ -0,0 +1,71 @@
|
|||
import { EvmChain, PrivateKey } from "../src";
|
||||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import Web3 from "web3";
|
||||
import { Contract } from "web3-eth-contract";
|
||||
|
||||
interface DeployConfig {
|
||||
gasMultiplier: number;
|
||||
gasPriceMultiplier: number;
|
||||
jsonOutputDir: string;
|
||||
privateKey: PrivateKey;
|
||||
}
|
||||
|
||||
// Deploys a contract if it was not deployed before.
|
||||
// It will check for the past deployments in file `cacheFile` against a key
|
||||
// If `cacheKey` is provided it will be used as the key, else it will use
|
||||
// a key - `${chain.getId()}-${artifactName}`
|
||||
export async function deployIfNotCached(
|
||||
cacheFile: string,
|
||||
chain: EvmChain,
|
||||
config: DeployConfig,
|
||||
artifactName: string,
|
||||
deployArgs: any[], // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
cacheKey?: string
|
||||
): Promise<string> {
|
||||
const cache = existsSync(cacheFile)
|
||||
? JSON.parse(readFileSync(cacheFile, "utf8"))
|
||||
: {};
|
||||
|
||||
const key = cacheKey ?? `${chain.getId()}-${artifactName}`;
|
||||
if (cache[key]) {
|
||||
const address = cache[key];
|
||||
console.log(
|
||||
`Using cached deployment of ${artifactName} on ${chain.getId()} at ${address}`
|
||||
);
|
||||
return address;
|
||||
}
|
||||
|
||||
const artifact = JSON.parse(
|
||||
readFileSync(join(config.jsonOutputDir, `${artifactName}.json`), "utf8")
|
||||
);
|
||||
|
||||
console.log(`Deploying ${artifactName} on ${chain.getId()}...`);
|
||||
|
||||
const addr = await chain.deploy(
|
||||
config.privateKey,
|
||||
artifact["abi"],
|
||||
artifact["bytecode"],
|
||||
deployArgs,
|
||||
config.gasMultiplier,
|
||||
config.gasPriceMultiplier
|
||||
);
|
||||
|
||||
console.log(`✅ Deployed ${artifactName} on ${chain.getId()} at ${addr}`);
|
||||
|
||||
cache[key] = addr;
|
||||
writeFileSync(cacheFile, JSON.stringify(cache, null, 2));
|
||||
return addr;
|
||||
}
|
||||
|
||||
export function getWeb3Contract(
|
||||
jsonOutputDir: string,
|
||||
artifactName: string,
|
||||
address: string
|
||||
): Contract {
|
||||
const artifact = JSON.parse(
|
||||
readFileSync(join(jsonOutputDir, `${artifactName}.json`), "utf8")
|
||||
);
|
||||
const web3 = new Web3();
|
||||
return new web3.eth.Contract(artifact["abi"], address);
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import { EvmChain } from "../src/chains";
|
||||
import { DefaultStore } from "../src/store";
|
||||
import {
|
||||
DeploymentType,
|
||||
EvmEntropyContract,
|
||||
getDefaultDeploymentConfig,
|
||||
PrivateKey,
|
||||
toDeploymentType,
|
||||
toPrivateKey,
|
||||
} from "../src";
|
||||
import { deployIfNotCached, getWeb3Contract } from "./common";
|
||||
|
||||
type DeploymentConfig = {
|
||||
type: DeploymentType;
|
||||
gasMultiplier: number;
|
||||
gasPriceMultiplier: number;
|
||||
privateKey: PrivateKey;
|
||||
jsonOutputDir: string;
|
||||
wormholeAddr: string;
|
||||
saveContract: boolean;
|
||||
};
|
||||
|
||||
const CACHE_FILE = ".cache-deploy-evm-entropy-contracts";
|
||||
const ENTROPY_DEFAULT_PROVIDER = {
|
||||
mainnet: "0x4b3D8aA4F753b278323EE88996dffDCd8fBFdBFC",
|
||||
testnet: "0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344",
|
||||
};
|
||||
|
||||
const parser = yargs(hideBin(process.argv))
|
||||
.scriptName("deploy_evm_entropy_contracts.ts")
|
||||
.usage(
|
||||
"Usage: $0 --std-output-dir <path/to/std-output-dir/> --private-key <private-key> --chain <chain0> --chain <chain1>"
|
||||
)
|
||||
.options({
|
||||
"std-output-dir": {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Path to the standard JSON output of the contracts (build artifact) directory",
|
||||
},
|
||||
"private-key": {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Private key to use for the deployment",
|
||||
},
|
||||
chain: {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Chain to upload the contract on. Can be one of the evm chains available in the store",
|
||||
},
|
||||
"deployment-type": {
|
||||
type: "string",
|
||||
demandOption: false,
|
||||
default: "stable",
|
||||
desc: "Deployment type to use. Can be 'stable' or 'beta'",
|
||||
},
|
||||
"gas-multiplier": {
|
||||
type: "number",
|
||||
demandOption: false,
|
||||
// Proxy (ERC1967) contract gas estimate is insufficient in many networks and thus we use 2 by default to make it work.
|
||||
default: 2,
|
||||
desc: "Gas multiplier to use for the deployment. This is useful when gas estimates are not accurate",
|
||||
},
|
||||
"gas-price-multiplier": {
|
||||
type: "number",
|
||||
demandOption: false,
|
||||
default: 1,
|
||||
desc: "Gas price multiplier to use for the deployment. This is useful when gas price estimates are not accurate",
|
||||
},
|
||||
"save-contract": {
|
||||
type: "boolean",
|
||||
demandOption: false,
|
||||
default: true,
|
||||
desc: "Save the contract to the store",
|
||||
},
|
||||
// TODO: maintain a wormhole store
|
||||
"wormhole-addr": {
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
desc: "Wormhole address",
|
||||
},
|
||||
});
|
||||
|
||||
async function deployExecutorContracts(
|
||||
chain: EvmChain,
|
||||
config: DeploymentConfig
|
||||
): Promise<string> {
|
||||
const executorImplAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"ExecutorUpgradable",
|
||||
[]
|
||||
);
|
||||
|
||||
// Craft the init data for the proxy contract
|
||||
const { governanceDataSource } = getDefaultDeploymentConfig(config.type);
|
||||
|
||||
const executorImplContract = getWeb3Contract(
|
||||
config.jsonOutputDir,
|
||||
"ExecutorUpgradable",
|
||||
executorImplAddr
|
||||
);
|
||||
|
||||
const executorInitData = executorImplContract.methods
|
||||
.initialize(
|
||||
config.wormholeAddr,
|
||||
0, // lastExecutedSequence,
|
||||
chain.getWormholeChainId(),
|
||||
governanceDataSource.emitterChain,
|
||||
`0x${governanceDataSource.emitterAddress}`
|
||||
)
|
||||
.encodeABI();
|
||||
|
||||
return await deployIfNotCached(CACHE_FILE, chain, config, "ERC1967Proxy", [
|
||||
executorImplAddr,
|
||||
executorInitData,
|
||||
]);
|
||||
}
|
||||
|
||||
async function deployEntropyContracts(
|
||||
chain: EvmChain,
|
||||
config: DeploymentConfig,
|
||||
executorAddr: string
|
||||
): Promise<string> {
|
||||
const entropyImplAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"EntropyUpgradable",
|
||||
[]
|
||||
);
|
||||
|
||||
const entropyImplContract = getWeb3Contract(
|
||||
config.jsonOutputDir,
|
||||
"EntropyUpgradable",
|
||||
entropyImplAddr
|
||||
);
|
||||
|
||||
const entropyInitData = entropyImplContract.methods
|
||||
.initialize(
|
||||
executorAddr, // owner
|
||||
executorAddr, // admin
|
||||
1, // pythFeeInWei
|
||||
chain.isMainnet()
|
||||
? ENTROPY_DEFAULT_PROVIDER.mainnet
|
||||
: ENTROPY_DEFAULT_PROVIDER.testnet,
|
||||
true // prefillRequestStorage
|
||||
)
|
||||
.encodeABI();
|
||||
|
||||
return await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"ERC1967Proxy",
|
||||
[entropyImplAddr, entropyInitData],
|
||||
// NOTE: we are deploying a ERC1967Proxy when deploying executor
|
||||
// we need to provide a different cache key. As the `artifactname`
|
||||
// is same in both case which means the cache key will be same
|
||||
`${chain.getId()}-ERC1967Proxy-ENTROPY`
|
||||
);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const argv = await parser.argv;
|
||||
|
||||
const deploymentConfig: DeploymentConfig = {
|
||||
type: toDeploymentType(argv.deploymentType),
|
||||
gasMultiplier: argv.gasMultiplier,
|
||||
gasPriceMultiplier: argv.gasPriceMultiplier,
|
||||
privateKey: toPrivateKey(argv.privateKey),
|
||||
jsonOutputDir: argv.stdOutputDir,
|
||||
saveContract: argv.saveContract,
|
||||
wormholeAddr: argv.wormholeAddr,
|
||||
};
|
||||
|
||||
console.log(
|
||||
`Deployment config: ${JSON.stringify(deploymentConfig, null, 2)}\n`
|
||||
);
|
||||
|
||||
const chainName = argv.chain;
|
||||
const chain = DefaultStore.chains[chainName];
|
||||
if (!chain) {
|
||||
throw new Error(`Chain ${chainName} not found`);
|
||||
} else if (!(chain instanceof EvmChain)) {
|
||||
throw new Error(`Chain ${chainName} is not an EVM chain`);
|
||||
}
|
||||
|
||||
console.log(`Deploying entropy contracts on ${chain.getId()}...`);
|
||||
|
||||
const executorAddr = await deployExecutorContracts(chain, deploymentConfig);
|
||||
const entropyAddr = await deployEntropyContracts(
|
||||
chain,
|
||||
deploymentConfig,
|
||||
executorAddr
|
||||
);
|
||||
|
||||
if (deploymentConfig.saveContract) {
|
||||
console.log("Saving the contract in the store...");
|
||||
const contract = new EvmEntropyContract(chain, entropyAddr);
|
||||
DefaultStore.entropy_contracts[contract.getId()] = contract;
|
||||
DefaultStore.saveAllContracts();
|
||||
}
|
||||
|
||||
console.log(
|
||||
`✅ Deployed entropy contracts on ${chain.getId()} at ${entropyAddr}\n\n`
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
|
@ -2,7 +2,6 @@ import yargs from "yargs";
|
|||
import { hideBin } from "yargs/helpers";
|
||||
import { EvmChain } from "../src/chains";
|
||||
import { DefaultStore } from "../src/store";
|
||||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||
import {
|
||||
DeploymentType,
|
||||
EvmPriceFeedContract,
|
||||
|
@ -12,9 +11,7 @@ import {
|
|||
toPrivateKey,
|
||||
WormholeEvmContract,
|
||||
} from "../src";
|
||||
import { join } from "path";
|
||||
import Web3 from "web3";
|
||||
import { Contract } from "web3-eth-contract";
|
||||
import { deployIfNotCached, getWeb3Contract } from "./common";
|
||||
|
||||
type DeploymentConfig = {
|
||||
type: DeploymentType;
|
||||
|
@ -89,64 +86,12 @@ const parser = yargs(hideBin(process.argv))
|
|||
},
|
||||
});
|
||||
|
||||
async function deployIfNotCached(
|
||||
chain: EvmChain,
|
||||
config: DeploymentConfig,
|
||||
artifactName: string,
|
||||
deployArgs: any[] // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
): Promise<string> {
|
||||
const cache = existsSync(CACHE_FILE)
|
||||
? JSON.parse(readFileSync(CACHE_FILE, "utf8"))
|
||||
: {};
|
||||
|
||||
const cacheKey = `${chain.getId()}-${artifactName}`;
|
||||
if (cache[cacheKey]) {
|
||||
const address = cache[cacheKey];
|
||||
console.log(
|
||||
`Using cached deployment of ${artifactName} on ${chain.getId()} at ${address}`
|
||||
);
|
||||
return address;
|
||||
}
|
||||
|
||||
const artifact = JSON.parse(
|
||||
readFileSync(join(config.jsonOutputDir, `${artifactName}.json`), "utf8")
|
||||
);
|
||||
|
||||
console.log(`Deploying ${artifactName} on ${chain.getId()}...`);
|
||||
|
||||
const addr = await chain.deploy(
|
||||
config.privateKey,
|
||||
artifact["abi"],
|
||||
artifact["bytecode"],
|
||||
deployArgs,
|
||||
config.gasMultiplier,
|
||||
config.gasPriceMultiplier
|
||||
);
|
||||
|
||||
console.log(`✅ Deployed ${artifactName} on ${chain.getId()} at ${addr}`);
|
||||
|
||||
cache[cacheKey] = addr;
|
||||
writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
|
||||
return addr;
|
||||
}
|
||||
|
||||
function getWeb3Contract(
|
||||
config: DeploymentConfig,
|
||||
artifactName: string,
|
||||
address: string
|
||||
): Contract {
|
||||
const artifact = JSON.parse(
|
||||
readFileSync(join(config.jsonOutputDir, `${artifactName}.json`), "utf8")
|
||||
);
|
||||
const web3 = new Web3();
|
||||
return new web3.eth.Contract(artifact["abi"], address);
|
||||
}
|
||||
|
||||
async function deployWormholeReceiverContracts(
|
||||
chain: EvmChain,
|
||||
config: DeploymentConfig
|
||||
): Promise<string> {
|
||||
const receiverSetupAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"ReceiverSetup",
|
||||
|
@ -154,6 +99,7 @@ async function deployWormholeReceiverContracts(
|
|||
);
|
||||
|
||||
const receiverImplAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"ReceiverImplementation",
|
||||
|
@ -162,7 +108,7 @@ async function deployWormholeReceiverContracts(
|
|||
|
||||
// Craft the init data for the proxy contract
|
||||
const setupContract = getWeb3Contract(
|
||||
config,
|
||||
config.jsonOutputDir,
|
||||
"ReceiverSetup",
|
||||
receiverSetupAddr
|
||||
);
|
||||
|
@ -180,6 +126,7 @@ async function deployWormholeReceiverContracts(
|
|||
.encodeABI();
|
||||
|
||||
const wormholeReceiverAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"WormholeReceiver",
|
||||
|
@ -207,6 +154,7 @@ async function deployPriceFeedContracts(
|
|||
wormholeAddr: string
|
||||
): Promise<string> {
|
||||
const pythImplAddr = await deployIfNotCached(
|
||||
CACHE_FILE,
|
||||
chain,
|
||||
config,
|
||||
"PythUpgradable",
|
||||
|
@ -219,7 +167,7 @@ async function deployPriceFeedContracts(
|
|||
);
|
||||
|
||||
const pythImplContract = getWeb3Contract(
|
||||
config,
|
||||
config.jsonOutputDir,
|
||||
"PythUpgradable",
|
||||
pythImplAddr
|
||||
);
|
||||
|
@ -237,7 +185,7 @@ async function deployPriceFeedContracts(
|
|||
)
|
||||
.encodeABI();
|
||||
|
||||
return await deployIfNotCached(chain, config, "ERC1967Proxy", [
|
||||
return await deployIfNotCached(CACHE_FILE, chain, config, "ERC1967Proxy", [
|
||||
pythImplAddr,
|
||||
pythInitData,
|
||||
]);
|
||||
|
|
Loading…
Reference in New Issue