wormhole/clients/js/evm.ts

146 lines
4.7 KiB
TypeScript

import { BridgeImplementation__factory, Implementation__factory, NFTBridgeImplementation__factory } from "@certusone/wormhole-sdk"
import { ethers } from "ethers"
import { NETWORKS } from "./networks"
import { impossible, Payload } from "./vaa"
import { Contracts, CONTRACTS, EVMChainName } from "@certusone/wormhole-sdk"
import axios from "axios";
import * as celo from "@celo-tools/celo-ethers-wrapper";
export async function execute_governance_evm(
payload: Payload,
vaa: Buffer,
network: "MAINNET" | "TESTNET" | "DEVNET",
chain: EVMChainName
) {
let n = NETWORKS[network][chain]
if (!n.rpc) {
throw Error(`No ${network} rpc defined for ${chain} (see networks.ts)`)
}
if (!n.key) {
throw Error(`No ${network} key defined for ${chain} (see networks.ts)`)
}
let rpc: string = n.rpc
let key: string = n.key
let contracts: Contracts = CONTRACTS[network][chain]
let provider = undefined
let signer = undefined
if (chain === "celo") {
provider = new celo.CeloProvider(rpc)
await provider.ready
signer = new celo.CeloWallet(key, provider)
} else {
provider = new ethers.providers.JsonRpcProvider(rpc)
signer = new ethers.Wallet(key, provider)
}
// Here we apply a set of chain-specific overrides.
// NOTE: some of these might have only been tested on mainnet. If it fails in
// testnet (or devnet), they might require additional guards
let overrides: ethers.Overrides = {}
if (chain === "karura" || chain == "acala") {
overrides = await getKaruraGasParams(n.rpc)
} else if (chain === "polygon") {
let feeData = await provider.getFeeData();
overrides = {
maxFeePerGas: feeData.maxFeePerGas?.mul(50) || undefined,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas?.mul(50) || undefined,
};
} else if (chain === "klaytn" || chain === "fantom") {
overrides = { gasPrice: (await signer.getGasPrice()).toString() }
}
switch (payload.module) {
case "Core":
if (contracts.core === undefined) {
throw Error(`Unknown core contract on ${network} for ${chain}`)
}
let c = new Implementation__factory(signer)
let cb = c.attach(contracts.core)
switch (payload.type) {
case "GuardianSetUpgrade":
console.log("Submitting new guardian set")
console.log("Hash: " + (await cb.submitNewGuardianSet(vaa, overrides)).hash)
break
case "ContractUpgrade":
console.log("Upgrading core contract")
console.log("Hash: " + (await cb.submitContractUpgrade(vaa, overrides)).hash)
break
default:
impossible(payload)
}
break
case "NFTBridge":
if (contracts.nft_bridge === undefined) {
throw Error(`Unknown nft bridge contract on ${network} for ${chain}`)
}
let n = new NFTBridgeImplementation__factory(signer)
let nb = n.attach(contracts.nft_bridge)
switch (payload.type) {
case "ContractUpgrade":
console.log("Upgrading contract")
console.log("Hash: " + (await nb.upgrade(vaa, overrides)).hash)
console.log("Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions")
break
case "RegisterChain":
console.log("Registering chain")
console.log("Hash: " + (await nb.registerChain(vaa, overrides)).hash)
break
default:
impossible(payload)
}
break
case "TokenBridge":
if (contracts.token_bridge === undefined) {
throw Error(`Unknown token bridge contract on ${network} for ${chain}`)
}
let t = new BridgeImplementation__factory(signer)
let tb = t.attach(contracts.token_bridge)
switch (payload.type) {
case "ContractUpgrade":
console.log("Upgrading contract")
console.log("Hash: " + (await tb.upgrade(vaa, overrides)).hash)
console.log("Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions")
break
case "RegisterChain":
console.log("Registering chain")
console.log("Hash: " + (await tb.registerChain(vaa, overrides)).hash)
break
default:
impossible(payload)
}
break
default:
impossible(payload)
}
}
export async function getKaruraGasParams(rpc: string): Promise<{
gasPrice: number;
gasLimit: number;
}> {
const gasLimit = 21000000;
const storageLimit = 64001;
const res = (
await axios.post(rpc, {
id: 0,
jsonrpc: "2.0",
method: "eth_getEthGas",
params: [
{
gasLimit,
storageLimit,
},
],
})
).data.result;
return {
gasLimit: parseInt(res.gasLimit, 16),
gasPrice: parseInt(res.gasPrice, 16),
};
}