typescript tooling major refactor

This commit is contained in:
chase-45 2023-01-07 00:14:24 -05:00 committed by Joe Howarth
parent d49fec47cc
commit 2dc8d45b95
24 changed files with 795 additions and 627 deletions

3
ethereum/.gitignore vendored
View File

@ -7,3 +7,6 @@ lib
node_modules
wormhole
ts-scripts/output
ts-scripts/.env
ts-scripts/.env.testnet
ts-scripts/.env.mainnet

View File

@ -23,7 +23,7 @@
"flatten": "mkdir -p node_modules/@poanet/solidity-flattener/contracts && cp -r contracts/* node_modules/@poanet/solidity-flattener/contracts/ && poa-solidity-flattener",
"registerChains": "ts-node ./ts-scripts/registerChains.ts",
"messageTest": "ts-node ./ts-scripts/messageTest.ts",
"deployAndConfigureTilt": "ENV=tilt ts-node ./ts-scripts/deployAndConfigure.ts"
"deployAndConfigureTilt": "ENV=tilt bash ./ts-scripts/shell/deployConfigureTest.sh"
},
"author": "",
"license": "ISC",

View File

@ -1,23 +0,0 @@
{
"chains": [
{
"id": 1337,
"wormholeId": 2,
"rpc": "http://localhost:8545",
"wormholeAddress": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
},
{
"id": 1397,
"wormholeId": 4,
"rpc": "http://localhost:8546",
"wormholeAddress": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
}
],
"defaultCoreRelayerConfig": {},
"defaultRelayProviderConfig": {
"deliverGasOverhead": "350000",
"updatePriceGas": "300000000000",
"updatePriceNative": "100000",
"maximumBudget": "1000000000000000000"
}
}

View File

@ -0,0 +1,17 @@
{
"description": "This file contains the chains against which all the scripts should run.",
"chains": [
{
"evmNetworkId": 1337,
"chainId": 2,
"rpc": "http://localhost:8545",
"wormholeAddress": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
},
{
"evmNetworkId": 1397,
"chainId": 4,
"rpc": "http://localhost:8546",
"wormholeAddress": "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
}
]
}

View File

@ -0,0 +1,34 @@
{
"description": "This file contains the addresses for the relayProviderProxy and CoreRelayerProxy on each chain. If useLastRun is true, this file will be ignored, and the addresses will be taken from the lastrun.json of the deployment scripts.",
"useLastRun": true,
"relayProviders": [
{
"chainId": 2,
"address": ""
},
{
"chainId": 4,
"address": ""
}
],
"coreRelayers": [
{
"chainId": 2,
"address": ""
},
{
"chainId": 4,
"address": ""
}
],
"mockIntegrations": [
{
"chainId": 2,
"address": ""
},
{
"chainId": 4,
"address": ""
}
]
}

View File

@ -0,0 +1,37 @@
{
"addresses": [
{
"chainId": 2,
"rewardAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1",
"approvedSenders": {
"address": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1",
"approved": true
}
},
{
"chainId": 4,
"rewardAddress": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1",
"approvedSenders": {
"address": "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1",
"approved": true
}
}
],
"pricingInfo": [
{
"chainId": 2,
"deliverGasOverhead": "350000",
"updatePriceGas": "300000000000",
"updatePriceNative": "100000",
"maximumBudget": "1000000000000000000"
},
{
"chainId": 4,
"deliverGasOverhead": "350000",
"updatePriceGas": "300000000000",
"updatePriceNative": "100000",
"maximumBudget": "1000000000000000000"
}
]
}

View File

@ -0,0 +1,104 @@
import { CoreRelayerProxy__factory } from "../../../sdk/src/ethers-contracts/factories/CoreRelayerProxy__factory"
import { CoreRelayerSetup__factory } from "../../../sdk/src/ethers-contracts/factories/CoreRelayerSetup__factory"
import { CoreRelayerImplementation__factory } from "../../../sdk/src/ethers-contracts/factories/CoreRelayerImplementation__factory"
import {
init,
loadChains,
writeOutputFiles,
ChainInfo,
Deployment,
getRelayProviderAddress,
getSigner,
} from "../helpers/env"
import { ethers } from "ethers"
const processName = "deployCoreRelayer"
init()
const chains = loadChains()
async function run() {
console.log("Start! " + processName)
const output: any = {
coreRelayerImplementations: [],
coreRelayerSetups: [],
coreRelayerProxies: [],
}
for (let i = 0; i < chains.length; i++) {
const coreRelayerImplementation = await deployCoreRelayerImplementation(chains[i])
const coreRelayerSetup = await deployCoreRelayerSetup(chains[i])
const coreRelayerProxy = await deployCoreRelayerProxy(
chains[i],
coreRelayerSetup.address,
coreRelayerImplementation.address,
chains[i].wormholeAddress,
getRelayProviderAddress(chains[i])
)
output.coreRelayerImplementations.push(coreRelayerImplementation)
output.coreRelayerSetups.push(coreRelayerSetup)
output.coreRelayerProxies.push(coreRelayerProxy)
}
writeOutputFiles(output, processName)
}
async function deployCoreRelayerImplementation(chain: ChainInfo): Promise<Deployment> {
console.log("deployCoreRelayerImplementation " + chain.chainId)
const signer = getSigner(chain)
const contractInterface = CoreRelayerImplementation__factory.createInterface()
const bytecode = CoreRelayerImplementation__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
async function deployCoreRelayerSetup(chain: ChainInfo): Promise<Deployment> {
console.log("deployCoreRelayerSetup " + chain.chainId)
const signer = getSigner(chain)
const contractInterface = CoreRelayerSetup__factory.createInterface()
const bytecode = CoreRelayerSetup__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
async function deployCoreRelayerProxy(
chain: ChainInfo,
coreRelayerSetupAddress: string,
coreRelayerImplementationAddress: string,
wormholeAddress: string,
relayProviderProxyAddress: string
): Promise<Deployment> {
console.log("deployCoreRelayerProxy " + chain.chainId)
const signer = getSigner(chain)
const contractInterface = CoreRelayerProxy__factory.createInterface()
const bytecode = CoreRelayerProxy__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
let ABI = ["function setup(address,uint16,address,address)"]
let iface = new ethers.utils.Interface(ABI)
let encodedData = iface.encodeFunctionData("setup", [
coreRelayerImplementationAddress,
chain.chainId,
wormholeAddress,
relayProviderProxyAddress,
])
const contract = await factory.deploy(coreRelayerSetupAddress, encodedData)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
run().then(() => console.log("Done! " + processName))

View File

@ -0,0 +1,41 @@
import { tryNativeToHexString } from "@certusone/wormhole-sdk"
import {
init,
loadChains,
ChainInfo,
getCoreRelayer,
getRelayProviderAddress,
getCoreRelayerAddress,
} from "../helpers/env"
const processName = "registerChainsCoreRelayer"
init()
const chains = loadChains()
async function run() {
console.log("Start! " + processName)
for (let i = 0; i < chains.length; i++) {
await registerChainsCoreRelayer(chains[i])
}
}
async function registerChainsCoreRelayer(chain: ChainInfo) {
console.log("registerChainsCoreRelayer " + chain.chainId)
const coreRelayer = getCoreRelayer(chain)
const relayProviderAddress = getRelayProviderAddress(chain)
await coreRelayer.setDefaultRelayProvider(relayProviderAddress)
for (let i = 0; i < chains.length; i++) {
await coreRelayer.registerCoreRelayerContract(
chains[i].chainId,
"0x" + tryNativeToHexString(getCoreRelayerAddress(chains[i]), "ethereum")
)
}
console.log("Did all contract registrations for the core relayer on " + chain.chainId)
}
run().then(() => console.log("Done! " + processName))

View File

@ -1,306 +0,0 @@
import { ChainId, tryNativeToHexString } from "@certusone/wormhole-sdk"
import { CoreRelayer__factory } from "../../sdk/src/ethers-contracts/factories/CoreRelayer__factory"
import { CoreRelayerProxy__factory } from "../../sdk/src/ethers-contracts/factories/CoreRelayerProxy__factory"
import { CoreRelayerSetup__factory } from "../../sdk/src/ethers-contracts/factories/CoreRelayerSetup__factory"
import { CoreRelayerImplementation__factory } from "../../sdk/src/ethers-contracts/factories/CoreRelayerImplementation__factory"
import { RelayProvider__factory } from "../../sdk/src/ethers-contracts/factories/RelayProvider__factory"
import { RelayProviderProxy__factory } from "../../sdk/src/ethers-contracts/factories/RelayProviderProxy__factory"
import { RelayProviderSetup__factory } from "../../sdk/src/ethers-contracts/factories/RelayProviderSetup__factory"
import { RelayProviderImplementation__factory } from "../../sdk/src/ethers-contracts/factories/RelayProviderImplementation__factory"
import { MockRelayerIntegration__factory } from "../../sdk/src/ethers-contracts/factories/MockRelayerIntegration__factory"
import { ethers } from "ethers"
import fs from "fs"
type Deployment = { chainId: ChainId; address: string }
function get_env_var(env: string): string {
const v = process.env[env]
return v || ""
}
const env = get_env_var("ENV")
if (!env) {
console.log("No environment was specified, using default environment files")
}
import * as dotenv from "dotenv"
dotenv.config({
path: `./ts-scripts/.env${env ? "." + env : ""}`,
})
const configFile = fs.readFileSync(`./ts-scripts/config/${env ? env : "config"}.json`)
const config = JSON.parse(configFile.toString())
const guardianKey = get_env_var("GUARDIAN_KEY")
const privateKey = get_env_var("WALLET_KEY")
if (!config) {
console.log("Failed to pull config file.")
}
if (!guardianKey) {
console.log("Failed to pull guardian key.")
}
if (!privateKey) {
console.log("Failed to pull wallet pk.")
}
async function run() {
console.log("Start!")
const output: any = {
relayProviderImplementations: [],
relayProviderSetups: [],
relayProviderProxys: [],
coreRelayerImplementations: [],
coreRelayerSetups: [],
coreRelayerProxys: [],
mockRelayerIntegrations: [],
}
for (let i = 0; i < config.chains.length; i++) {
const relayProviderImplementation = await deployRelayProviderImplementation(
config.chains[i]
)
const relayProviderSetup = await deployRelayProviderSetup(config.chains[i])
const relayProviderProxy = await deployRelayProviderProxy(
config.chains[i],
relayProviderSetup.address,
relayProviderImplementation.address
)
const coreRelayerImplementation = await deployCoreRelayerImplementation(
config.chains[i]
)
const coreRelayerSetup = await deployCoreRelayerSetup(config.chains[i])
const coreRelayerProxy = await deployCoreRelayerProxy(
config.chains[i],
coreRelayerSetup.address,
coreRelayerImplementation.address,
config.chains[i].wormholeAddress,
relayProviderProxy.address
)
const mockRelayerIntegration = await deployMockRelayerIntegration(
config.chains[i],
config.chains[i].wormholeAddress,
coreRelayerProxy.address
)
output.relayProviderImplementations.push(relayProviderImplementation)
output.relayProviderSetups.push(relayProviderSetup)
output.relayProviderProxys.push(relayProviderProxy)
output.coreRelayerImplementations.push(coreRelayerImplementation)
output.coreRelayerSetups.push(coreRelayerSetup)
output.coreRelayerProxys.push(coreRelayerProxy)
output.mockRelayerIntegrations.push(mockRelayerIntegration)
}
for (let i = 0; i < config.chains.length; i++) {
await configureCoreRelayer(config.chains[i], output.coreRelayerProxys)
await configureRelayProvider(
output.relayProviderProxys.find(
(x: any) => x.chainId == config.chains[i].wormholeId
),
config.chains
)
}
writeOutputFiles(output)
}
async function deployRelayProviderImplementation(chain: any): Promise<Deployment> {
console.log("deployRelayProviderImplementation " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderImplementation__factory.createInterface()
const bytecode = RelayProviderImplementation__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployRelayProviderSetup(chain: any): Promise<Deployment> {
console.log("deployRelayProviderSetup " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderSetup__factory.createInterface()
const bytecode = RelayProviderSetup__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployRelayProviderProxy(
chain: any,
relayProviderSetupAddress: string,
relayProviderImplementationAddress: string
): Promise<Deployment> {
console.log("deployRelayProviderProxy " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderProxy__factory.createInterface()
const bytecode = RelayProviderProxy__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
let ABI = ["function setup(address,uint16)"]
let iface = new ethers.utils.Interface(ABI)
let encodedData = iface.encodeFunctionData("setup", [
relayProviderImplementationAddress,
chain.wormholeId,
])
const contract = await factory.deploy(relayProviderSetupAddress, encodedData)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployCoreRelayerImplementation(chain: any): Promise<Deployment> {
console.log("deployCoreRelayerImplementation " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = CoreRelayerImplementation__factory.createInterface()
const bytecode = CoreRelayerImplementation__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployCoreRelayerSetup(chain: any): Promise<Deployment> {
console.log("deployCoreRelayerSetup " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = CoreRelayerSetup__factory.createInterface()
const bytecode = CoreRelayerSetup__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployCoreRelayerProxy(
chain: any,
coreRelayerSetupAddress: string,
coreRelayerImplementationAddress: string,
wormholeAddress: string,
relayProviderProxyAddress: string
): Promise<Deployment> {
console.log("deployCoreRelayerProxy " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = CoreRelayerProxy__factory.createInterface()
const bytecode = CoreRelayerProxy__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
let ABI = ["function setup(address,uint16,address,address)"]
let iface = new ethers.utils.Interface(ABI)
let encodedData = iface.encodeFunctionData("setup", [
coreRelayerImplementationAddress,
chain.wormholeId,
wormholeAddress,
relayProviderProxyAddress,
])
const contract = await factory.deploy(coreRelayerSetupAddress, encodedData)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function deployMockRelayerIntegration(
chain: any,
wormholeAddress: string,
coreRelayerProxy: string
): Promise<Deployment> {
console.log("deployMockRelayerIntegration " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = MockRelayerIntegration__factory.createInterface()
const bytecode = MockRelayerIntegration__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy(wormholeAddress, coreRelayerProxy)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.wormholeId }
})
}
async function configureCoreRelayer(chain: any, contracts: Deployment[]) {
console.log("configureCoreRelayer " + chain.wormholeId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contract = CoreRelayer__factory.connect(
contracts.find((x) => x.chainId == chain.wormholeId)?.address || "",
signer
)
for (let i = 0; i < config.chains.length; i++) {
await contract.registerCoreRelayerContract(
contracts[i].chainId,
"0x" + tryNativeToHexString(contracts[i].address, "ethereum")
)
}
console.log("registered all core relayers for " + chain.wormholeId)
}
async function configureRelayProvider(deployment: Deployment, chains: any) {
console.log("configureCoreRelayer " + deployment.chainId)
let provider = new ethers.providers.StaticJsonRpcProvider(
chains.find((x: any) => x.wormholeId == deployment.chainId).rpc || ""
)
let signer = new ethers.Wallet(privateKey, provider)
const contract = RelayProvider__factory.connect(deployment.address, signer)
const walletAddress = signer.address
const walletAddresswh = "0x" + tryNativeToHexString(walletAddress, "ethereum")
await contract.updateRewardAddress(walletAddress)
for (let i = 0; i < config.chains.length; i++) {
await contract.updateDeliverGasOverhead(
chains[i].wormholeId,
config.defaultRelayProviderConfig.deliverGasOverhead
)
await contract.updateDeliveryAddress(chains[i].wormholeId, walletAddresswh)
await contract.updateMaximumBudget(
chains[i].wormholeId,
config.defaultRelayProviderConfig.maximumBudget
)
await contract.updatePrice(
chains[i].wormholeId,
config.defaultRelayProviderConfig.updatePriceGas,
config.defaultRelayProviderConfig.updatePriceNative
)
}
console.log("configured relay provider for " + deployment.chainId)
}
function writeOutputFiles(output: any) {
fs.mkdirSync("./ts-scripts/output/deployAndConfigure/", { recursive: true })
fs.writeFileSync(
`./ts-scripts/output/deployAndConfigure/zlastrun-${env}.json`,
JSON.stringify(output),
{ flag: "w" }
)
fs.writeFileSync(
`./ts-scripts/output/deployAndConfigure/${Date.now()}-${env}.json`,
JSON.stringify(output),
{ flag: "w" }
)
}
run().then(() => console.log("Done!"))

View File

@ -0,0 +1,219 @@
import { ChainId } from "@certusone/wormhole-sdk"
import { ethers, Signer } from "ethers"
import fs from "fs"
import {
CoreRelayer,
RelayProvider,
RelayProvider__factory,
CoreRelayer__factory,
MockRelayerIntegration,
MockRelayerIntegration__factory,
} from "../../../sdk/src"
export type ChainInfo = {
evmNetworkId: number
chainId: ChainId
rpc: string
wormholeAddress: string
}
export type Deployment = {
chainId: ChainId
address: string
}
let env = ""
export function init() {
env = get_env_var("ENV")
if (!env) {
console.log("No environment was specified, using default environment files")
env = "default"
}
require("dotenv").config({
path: `./ts-scripts/.env${env != "default" ? "." + env : ""}`,
})
}
function get_env_var(env: string): string {
const v = process.env[env]
return v || ""
}
export function loadScriptConfig(processName: string): any {
const configFile = fs.readFileSync(
`./ts-scripts/config/${env}/scriptConfigs/${processName}.json`
)
const config = JSON.parse(configFile.toString())
if (!config) {
throw Error("Failed to pull config file!")
}
return config
}
export function loadChains(): ChainInfo[] {
const chainFile = fs.readFileSync(`./ts-scripts/config/${env}/chains.json`)
const chains = JSON.parse(chainFile.toString())
if (!chains.chains) {
throw Error("Failed to pull chain config file!")
}
return chains.chains
}
export function loadPrivateKey(): string {
const privateKey = get_env_var("WALLET_KEY")
if (!privateKey) {
throw Error("Failed to find private key for this process!")
}
return privateKey
}
export function loadRelayProviders(): Deployment[] {
const contractsFile = fs.readFileSync(`./ts-scripts/config/${env}/contracts.json`)
if (!contractsFile) {
throw Error("Failed to find contracts file for this process!")
}
const contracts = JSON.parse(contractsFile.toString())
if (contracts.useLastRun) {
const lastRunFile = fs.readFileSync(
`./ts-scripts/output/${env}/deployRelayProvider/lastrun.json`
)
if (!lastRunFile) {
throw Error("Failed to find last run file for the deployRelayProvider process!")
}
const lastRun = JSON.parse(lastRunFile.toString())
return lastRun.relayProviderProxies
} else if (contracts.useLastRun == false) {
return contracts.relayProviders
} else {
throw Error("useLastRun was an invalid value from the contracts config")
}
}
export function loadCoreRelayers(): Deployment[] {
const contractsFile = fs.readFileSync(`./ts-scripts/config/${env}/contracts.json`)
if (!contractsFile) {
throw Error("Failed to find contracts file for this process!")
}
const contracts = JSON.parse(contractsFile.toString())
if (contracts.useLastRun) {
const lastRunFile = fs.readFileSync(
`./ts-scripts/output/${env}/deployCoreRelayer/lastrun.json`
)
if (!lastRunFile) {
throw Error("Failed to find last run file for the Core Relayer process!")
}
const lastRun = JSON.parse(lastRunFile.toString())
return lastRun.coreRelayerProxies
} else {
return contracts.coreRelayers
}
}
export function loadMockIntegrations(): Deployment[] {
const contractsFile = fs.readFileSync(`./ts-scripts/config/${env}/contracts.json`)
if (!contractsFile) {
throw Error("Failed to find contracts file for this process!")
}
const contracts = JSON.parse(contractsFile.toString())
if (contracts.useLastRun) {
const lastRunFile = fs.readFileSync(
`./ts-scripts/output/${env}/deployMockIntegration/lastrun.json`
)
if (!lastRunFile) {
throw Error("Failed to find last run file for the deploy mock integration process!")
}
const lastRun = JSON.parse(lastRunFile.toString())
return lastRun.mockIntegrations
} else {
return contracts.mockIntegrations
}
}
export function loadGuardianKey(): string {
const guardianKey = get_env_var("GUARDIAN_KEY")
if (!guardianKey) {
throw Error("Failed to find guardian key for this process!")
}
return guardianKey
}
export function writeOutputFiles(output: any, processName: string) {
fs.mkdirSync(`./ts-scripts/output/${env}/${processName}`, { recursive: true })
fs.writeFileSync(
`./ts-scripts/output/${env}/${processName}/lastrun.json`,
JSON.stringify(output),
{ flag: "w" }
)
fs.writeFileSync(
`./ts-scripts/output/${env}/${processName}/${Date.now()}.json`,
JSON.stringify(output),
{ flag: "w" }
)
}
export function getSigner(chain: ChainInfo): Signer {
let provider = new ethers.providers.StaticJsonRpcProvider(
loadChains().find((x: any) => x.chainId == chain.chainId)?.rpc || ""
)
let signer = new ethers.Wallet(loadPrivateKey(), provider)
return signer
}
export function getRelayProviderAddress(chain: ChainInfo): string {
const thisChainsProvider = loadRelayProviders().find(
(x: any) => x.chainId == chain.chainId
)?.address
if (!thisChainsProvider) {
throw new Error(
"Failed to find a RelayProvider contract address on chain " + chain.chainId
)
}
return thisChainsProvider
}
export function getRelayProvider(chain: ChainInfo): RelayProvider {
const thisChainsProvider = getRelayProviderAddress(chain)
const contract = RelayProvider__factory.connect(thisChainsProvider, getSigner(chain))
return contract
}
export function getCoreRelayerAddress(chain: ChainInfo): string {
const thisChainsRelayer = loadCoreRelayers().find(
(x: any) => x.chainId == chain.chainId
)?.address
if (!thisChainsRelayer) {
throw new Error(
"Failed to find a CoreRelayer contract address on chain " + chain.chainId
)
}
return thisChainsRelayer
}
export function getCoreRelayer(chain: ChainInfo): CoreRelayer {
const thisChainsRelayer = getCoreRelayerAddress(chain)
const contract = CoreRelayer__factory.connect(thisChainsRelayer, getSigner(chain))
return contract
}
export function getMockIntegrationAddress(chain: ChainInfo): string {
const thisMock = loadMockIntegrations().find(
(x: any) => x.chainId == chain.chainId
)?.address
if (!thisMock) {
throw new Error(
"Failed to find a mock integration contract address on chain " + chain.chainId
)
}
return thisMock
}
export function getMockIntegration(chain: ChainInfo): MockRelayerIntegration {
const thisIntegration = getMockIntegrationAddress(chain)
const contract = MockRelayerIntegration__factory.connect(
thisIntegration,
getSigner(chain)
)
return contract
}

View File

@ -1,132 +0,0 @@
import { ChainId, RefundEscrow, tryNativeToHexString } from "@certusone/wormhole-sdk"
import { CoreRelayer__factory, MockRelayerIntegration__factory } from "../../sdk/src"
import { CoreRelayerStructs } from "../../sdk/src/ethers-contracts/CoreRelayer"
import { ethers } from "ethers"
import fs from "fs"
// tilt
// const CHAIN_INFOS = [
// {
// id: 1337,
// wormholeId: 2,
// rpc: "http://localhost:8545",
// contractAddress: "foo",
// },
// {
// id: 1397,
// wormholeId: 4,
// rpc: "http://localhost:8546",
// contractAddress: "foo",
// },
// ]
const CHAIN_INFOS = [
{
id: 44787,
wormholeId: 14,
rpc: "https://alfajores-forno.celo-testnet.org",
mockIntegrationAddress: "celo",
relayerAddress: "",
},
{
id: 43113,
wormholeId: 6,
rpc: "https://api.avax-test.network/ext/bc/C/rpc",
mockIntegrationAddress: "fuji",
relayerAddress: "",
},
]
async function run() {
if (!process.env["PRIVATE_KEY"]) {
console.log("Missing private key env var, falling back to tilt private key")
}
const pk =
process.env["PRIVATE_KEY"] ||
"0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"
//first collect all contract addresses
const promises = CHAIN_INFOS.map(async (info) => {
const file = await fs.readFileSync(
`./broadcast/deploy_contracts.sol/${info.id}/run-latest.json`
)
const content = JSON.parse(file.toString())
const createTransaction = content.transactions.find((x: any, index: any) => {
return x.contractName == "MockRelayerIntegration"
})
const createTransaction2 = content.transactions.find((x: any, index: any) => {
return x.contractName == "RelayProviderProxy" && index > 4
})
info.mockIntegrationAddress = createTransaction.contractAddress
info.relayerAddress = createTransaction2.contractAddress
console.log(`${info.wormholeId}: CoreRelayer: ${info.relayerAddress}`)
})
await Promise.all(promises)
const sourceChain = CHAIN_INFOS[1]
const targetChain = CHAIN_INFOS[0]
const sourceProvider = new ethers.providers.StaticJsonRpcProvider(sourceChain.rpc)
const targetProvider = new ethers.providers.StaticJsonRpcProvider(targetChain.rpc)
// signers
const sourceWallet = new ethers.Wallet(pk, sourceProvider)
const targetWallet = new ethers.Wallet(pk, targetProvider)
const mockIntegration = MockRelayerIntegration__factory.connect(
sourceChain.mockIntegrationAddress,
sourceWallet
)
const coreRelayer = CoreRelayer__factory.connect(
sourceChain.relayerAddress,
sourceWallet
)
// todo: remove
const x = await CoreRelayer__factory.connect(
targetChain.relayerAddress,
targetWallet
).registeredCoreRelayerContract(sourceChain.wormholeId)
console.log("should be fuji address", x)
const defaultRelayerProvider = await coreRelayer.getDefaultRelayProvider()
console.log("Default relay provider: ", defaultRelayerProvider)
const relayQuote = await (
await coreRelayer.quoteGasDeliveryFee(
targetChain.wormholeId,
2000000,
coreRelayer.getDefaultRelayProvider()
)
).add(10000000000)
const tx = await mockIntegration.sendMessageWithForwardedResponse(
Buffer.from("Hello World 3"),
targetChain.wormholeId,
targetChain.mockIntegrationAddress,
{
gasLimit: 1000000,
value: relayQuote,
}
)
const rx = await tx.wait()
console.log(rx, "da receipt")
}
// const tx = await mockIntegration.sendMessage(
// Buffer.from("Hello World 2"),
// targetChain.wormholeId,
// targetChain.mockIntegrationAddress,
// {
// gasLimit: 1000000,
// value: relayQuote,
// }
// )
// const rx = await tx.wait()
// console.log(rx, "da receipt")
// }
run().then(() => console.log("Done!"))
console.log("Start!")

View File

@ -0,0 +1,50 @@
import {
init,
loadChains,
loadPrivateKey,
writeOutputFiles,
ChainInfo,
Deployment,
} from "../helpers/env"
import { ethers } from "ethers"
import { getCoreRelayerAddress, getSigner } from "../helpers/env"
import { MockRelayerIntegration__factory } from "../../../sdk/src"
const processName = "deployMockIntegration"
init()
const chains = loadChains()
async function run() {
console.log("Start!")
const output: any = {
mockIntegrations: [],
}
for (let i = 0; i < chains.length; i++) {
const mockIntegration = await deployMockIntegration(chains[i])
output.mockIntegrations.push(mockIntegration)
}
writeOutputFiles(output, processName)
}
async function deployMockIntegration(chain: ChainInfo): Promise<Deployment> {
console.log("deployMockIntegration " + chain.chainId)
let signer = getSigner(chain)
const contractInterface = MockRelayerIntegration__factory.createInterface()
const bytecode = MockRelayerIntegration__factory.bytecode
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy(
chain.wormholeAddress,
getCoreRelayerAddress(chain)
)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
run().then(() => console.log("Done!"))

View File

@ -0,0 +1,63 @@
import {
getCoreRelayer,
getCoreRelayerAddress,
getMockIntegration,
getMockIntegrationAddress,
getRelayProviderAddress,
init,
loadChains,
} from "../helpers/env"
init()
const chains = loadChains()
async function run() {
const sourceChain = chains[0]
const targetChain = chains[1]
const sourceRelayer = getCoreRelayer(sourceChain)
// todo: remove
const registeredChain = await sourceRelayer.registeredCoreRelayerContract(
sourceChain.chainId
)
console.log("The source chain should be registered to itself")
console.log(registeredChain)
console.log(getCoreRelayerAddress(sourceChain))
console.log("")
const defaultRelayerProvider = await sourceRelayer.getDefaultRelayProvider()
console.log("Default relay provider should be this chains relayProvider ")
console.log(defaultRelayerProvider)
console.log(getRelayProviderAddress(sourceChain))
console.log("")
const relayQuote = await (
await sourceRelayer.quoteGasDeliveryFee(
targetChain.chainId,
2000000,
sourceRelayer.getDefaultRelayProvider()
)
).add(10000000000)
console.log("relay quote: " + relayQuote)
const mockIntegration = getMockIntegration(sourceChain)
const targetAddress = getMockIntegrationAddress(targetChain)
const tx = await mockIntegration.sendMessageWithForwardedResponse(
Buffer.from("Hello World 3"),
targetChain.chainId,
targetAddress,
targetAddress,
{
gasLimit: 1000000,
value: relayQuote,
}
)
const rx = await tx.wait()
console.log(rx, "da receipt")
}
run().then(() => console.log("Done!"))
console.log("Start!")

View File

@ -1,83 +0,0 @@
import { ChainId, RefundEscrow, tryNativeToHexString } from "@certusone/wormhole-sdk"
import { CoreRelayer__factory, MockRelayerIntegration__factory } from "../../sdk/src"
import { CoreRelayerStructs } from "../../sdk/src/ethers-contracts/CoreRelayer"
import { ethers } from "ethers"
import fs from "fs"
// tilt
// const CHAIN_INFOS = [
// {
// id: 1337,
// wormholeId: 2,
// rpc: "http://localhost:8545",
// contractAddress: "foo",
// },
// {
// id: 1397,
// wormholeId: 4,
// rpc: "http://localhost:8546",
// contractAddress: "foo",
// },
// ]
const CHAIN_INFOS = [
{
id: 44787,
wormholeId: 14,
rpc: "https://alfajores-forno.celo-testnet.org",
contractAddress: "celo",
},
{
id: 43113,
wormholeId: 6,
rpc: "https://api.avax-test.network/ext/bc/C/rpc",
contractAddress: "fuji",
},
]
async function run() {
if (!process.env["PRIVATE_KEY"]) {
console.log("Missing private key env var, falling back to tilt private key")
}
const pk =
process.env["PRIVATE_KEY"] ||
"0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"
//first collect all contract addresses
await Promise.all(
CHAIN_INFOS.map(async (info) => {
const file = await fs.readFileSync(
`./broadcast/deploy_contracts.sol/${info.id}/run-latest.json`
)
const content = JSON.parse(file.toString())
const createTransaction = content.transactions.find((x: any, index: any) => {
return x.contractName == "RelayProviderProxy" && index > 4
})
info.contractAddress = createTransaction.contractAddress
})
)
await Promise.all(
CHAIN_INFOS.map(async (info) => {
const provider = new ethers.providers.StaticJsonRpcProvider(info.rpc)
// signers
const wallet = new ethers.Wallet(pk, provider)
const coreRelayer = CoreRelayer__factory.connect(info.contractAddress, wallet)
for (const info2 of CHAIN_INFOS) {
if (info.wormholeId != info2.wormholeId) {
await coreRelayer.registerCoreRelayerContract(
info2.wormholeId,
"0x" + tryNativeToHexString(info2.contractAddress, "ethereum")
)
}
}
})
)
}
run().then(() => console.log("Done!"))
console.log("Start!")

View File

@ -0,0 +1,76 @@
import {
init,
loadChains,
ChainInfo,
loadScriptConfig,
getRelayProvider,
} from "../helpers/env"
const processName = "configureRelayProvider"
init()
const chains = loadChains()
const config = loadScriptConfig(processName)
async function run() {
console.log("Start! " + processName)
for (let i = 0; i < chains.length; i++) {
await configureChainsRelayProvider(chains[i])
}
}
async function configureChainsRelayProvider(chain: ChainInfo) {
console.log("about to perform configurations for chain " + chain.chainId)
const relayProvider = getRelayProvider(chain)
const thisChainsConfigInfo = config.addresses.find(
(x: any) => x.chainId == chain.chainId
)
if (!thisChainsConfigInfo) {
throw new Error("Failed to find address config info for chain " + chain.chainId)
}
if (!thisChainsConfigInfo.rewardAddress) {
throw new Error("Failed to find reward address info for chain " + chain.chainId)
}
if (!thisChainsConfigInfo.approvedSenders) {
throw new Error("Failed to find approvedSenders info for chain " + chain.chainId)
}
//Set address info
await relayProvider.updateRewardAddress(thisChainsConfigInfo.rewardAddress)
for (let i = 0; i < thisChainsConfigInfo.approvedSenders.length; i++) {
await relayProvider.updateApprovedSender(
thisChainsConfigInfo.approvedSenders[i].address,
thisChainsConfigInfo.approvedSenders[i].approved
)
}
//TODO refactor to use the batch price update, probably
for (let i = 0; i < chains.length; i++) {
const targetChainPriceUpdate = config.pricingInfo.find(
(x: any) => x.chainId == chains[i].chainId
)
if (!targetChainPriceUpdate) {
throw new Error("Failed to find pricingInfo for chain " + chains[i].chainId)
}
//delivery addresses are not done by this script, but rather the register chains script.
await relayProvider.updateDeliverGasOverhead(
chains[i].chainId,
targetChainPriceUpdate.deliverGasOverhead
)
await relayProvider.updatePrice(
chains[i].chainId,
targetChainPriceUpdate.updatePriceGas,
targetChainPriceUpdate.updatePriceNative
)
await relayProvider.updateMaximumBudget(
chains[i].chainId,
targetChainPriceUpdate.maximumBudget
)
}
console.log("done with registrations on " + chain.chainId)
}
run().then(() => console.log("Done! " + processName))

View File

@ -0,0 +1,103 @@
import { RelayProviderProxy__factory } from "../../../sdk/src/ethers-contracts/factories/RelayProviderProxy__factory"
import { RelayProviderSetup__factory } from "../../../sdk/src/ethers-contracts/factories/RelayProviderSetup__factory"
import { RelayProviderImplementation__factory } from "../../../sdk/src/ethers-contracts/factories/RelayProviderImplementation__factory"
import {
init,
loadChains,
loadPrivateKey,
writeOutputFiles,
ChainInfo,
Deployment,
} from "../helpers/env"
import { ethers } from "ethers"
const processName = "deployRelayProvider"
init()
const chains = loadChains()
const privateKey = loadPrivateKey()
async function run() {
console.log("Start!")
const output: any = {
relayProviderImplementations: [],
relayProviderSetups: [],
relayProviderProxies: [],
}
for (let i = 0; i < chains.length; i++) {
const relayProviderImplementation = await deployRelayProviderImplementation(chains[i])
const relayProviderSetup = await deployRelayProviderSetup(chains[i])
const relayProviderProxy = await deployRelayProviderProxy(
chains[i],
relayProviderSetup.address,
relayProviderImplementation.address
)
output.relayProviderImplementations.push(relayProviderImplementation)
output.relayProviderSetups.push(relayProviderSetup)
output.relayProviderProxies.push(relayProviderProxy)
}
writeOutputFiles(output, processName)
}
async function deployRelayProviderImplementation(chain: ChainInfo): Promise<Deployment> {
console.log("deployRelayProviderImplementation " + chain.chainId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderImplementation__factory.createInterface()
const bytecode = RelayProviderImplementation__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
async function deployRelayProviderSetup(chain: ChainInfo): Promise<Deployment> {
console.log("deployRelayProviderSetup " + chain.chainId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderSetup__factory.createInterface()
const bytecode = RelayProviderSetup__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
const contract = await factory.deploy()
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
async function deployRelayProviderProxy(
chain: ChainInfo,
relayProviderSetupAddress: string,
relayProviderImplementationAddress: string
): Promise<Deployment> {
console.log("deployRelayProviderProxy " + chain.chainId)
let provider = new ethers.providers.StaticJsonRpcProvider(chain.rpc)
let signer = new ethers.Wallet(privateKey, provider)
const contractInterface = RelayProviderProxy__factory.createInterface()
const bytecode = RelayProviderProxy__factory.bytecode
//@ts-ignore
const factory = new ethers.ContractFactory(contractInterface, bytecode, signer)
let ABI = ["function setup(address,uint16)"]
let iface = new ethers.utils.Interface(ABI)
let encodedData = iface.encodeFunctionData("setup", [
relayProviderImplementationAddress,
chain.chainId,
])
const contract = await factory.deploy(relayProviderSetupAddress, encodedData)
return await contract.deployed().then((result) => {
console.log("Successfully deployed contract at " + result.address)
return { address: result.address, chainId: chain.chainId }
})
}
run().then(() => console.log("Done!"))

View File

@ -0,0 +1,41 @@
import { tryNativeToHexString } from "@certusone/wormhole-sdk"
import {
init,
loadChains,
ChainInfo,
getCoreRelayerAddress,
getRelayProvider,
getRelayProviderAddress,
} from "../helpers/env"
const processName = "registerChainsRelayProvider"
init()
const chains = loadChains()
async function run() {
console.log("Start! " + processName)
for (let i = 0; i < chains.length; i++) {
await registerChainsRelayProvider(chains[i])
}
}
async function registerChainsRelayProvider(chain: ChainInfo) {
console.log("about to perform registrations for chain " + chain.chainId)
const relayProvider = getRelayProvider(chain)
const coreRelayerAddress = getCoreRelayerAddress(chain)
await relayProvider.updateCoreRelayer(coreRelayerAddress)
for (let i = 0; i < chains.length; i++) {
const targetChainProviderAddress = getRelayProviderAddress(chains[i])
const whAddress = "0x" + tryNativeToHexString(targetChainProviderAddress, "ethereum")
await relayProvider.updateDeliveryAddress(chains[i].chainId, whAddress)
}
console.log("done with registrations on " + chain.chainId)
}
run().then(() => console.log("Done! " + processName))

View File

@ -1,82 +0,0 @@
import { RelayProvider__factory } from "../../sdk/src"
import { ethers } from "ethers"
import fs from "fs"
import { tryNativeToHexString } from "@certusone/wormhole-sdk"
const CHAIN_INFOS = [
{
id: 44787,
wormholeId: 14,
rpc: "https://alfajores-forno.celo-testnet.org",
mockIntegrationAddress: "celo",
relayerAddress: "",
relayProvider: "",
},
{
id: 43113,
wormholeId: 6,
rpc: "https://api.avax-test.network/ext/bc/C/rpc",
mockIntegrationAddress: "fuji",
relayerAddress: "",
relayProvider: "",
},
]
async function run() {
if (!process.env["PRIVATE_KEY"]) {
console.log("Missing private key env var, falling back to tilt private key")
}
const pk =
process.env["PRIVATE_KEY"] ||
"0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"
//first collect all contract addresses
await Promise.all(
CHAIN_INFOS.map(async (info) => {
const file = await fs.readFileSync(
`./broadcast/deploy_contracts.sol/${info.id}/run-latest.json`
)
const content = JSON.parse(file.toString())
const createTransaction = content.transactions.find((x: any, index: any) => {
return x.contractName == "MockRelayerIntegration"
})
const relayProviderTx = content.transactions.find((x: any, index: any) => {
return x.contractName == "RelayProviderProxy" && index <= 4
})
const createTransaction2 = content.transactions.find((x: any, index: any) => {
return x.contractName == "RelayProviderProxy" && index > 4
})
info.mockIntegrationAddress = createTransaction.contractAddress
info.relayerAddress = createTransaction2.contractAddress
info.relayProvider = relayProviderTx.contractAddress
})
)
for (const info of CHAIN_INFOS) {
const rpc = new ethers.providers.StaticJsonRpcProvider(info.rpc)
const wallet = new ethers.Wallet(pk, rpc)
const relayerProvider = RelayProvider__factory.connect(info.relayProvider, wallet)
for (const { wormholeId } of CHAIN_INFOS) {
await relayerProvider
.updateDeliveryAddress(
wormholeId,
"0x" + tryNativeToHexString(wallet.address, "ethereum")
)
.then((tx) => tx.wait())
await relayerProvider
.updateRewardAddress(wallet.address)
.then((tx) => tx.wait())
console.log(
`Delivery address for chain ${wormholeId} on chain ${
info.wormholeId
}: ${await relayerProvider.getDeliveryAddress(wormholeId)}`
)
}
}
}
run().then(() => console.log("Done!"))
console.log("Start!")

View File

@ -0,0 +1 @@
ts-node ./ts-scripts/relayProvider/deployRelayProvider.ts && ts-node ./ts-scripts/coreRelayer/deployCoreRelayer.ts && ts-node ./ts-scripts/relayProvider/registerChainsRelayProvider.ts && ts-node ./ts-scripts/coreRelayer/registerChainsCoreRelayer.ts && ts-node ./ts-scripts/relayProvider/configureRelayProvider.ts && ts-node ./ts-scripts/mockIntegration/deployMockIntegration.ts && ts-node ./ts-scripts/mockIntegration/messageTest.ts