139 lines
5.3 KiB
TypeScript
139 lines
5.3 KiB
TypeScript
import yargs from "yargs";
|
|
import { hideBin } from "yargs/helpers";
|
|
import { CosmWasmChain, EvmChain } from "../src/chains";
|
|
import { createHash } from "crypto";
|
|
import { DefaultStore } from "../src/store";
|
|
import {
|
|
CosmosUpgradeContract,
|
|
EvmSetWormholeAddress,
|
|
EvmUpgradeContract,
|
|
getProposalInstructions,
|
|
MultisigParser,
|
|
WormholeMultisigInstruction,
|
|
} from "xc_admin_common";
|
|
import SquadsMesh from "@sqds/mesh";
|
|
import {
|
|
getPythClusterApiUrl,
|
|
PythCluster,
|
|
} from "@pythnetwork/client/lib/cluster";
|
|
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
|
|
import { AccountMeta, Keypair, PublicKey } from "@solana/web3.js";
|
|
import { EvmContract, WormholeEvmContract } from "../src/contracts/evm";
|
|
import Web3 from "web3";
|
|
|
|
const parser = yargs(hideBin(process.argv))
|
|
.usage("Usage: $0 --cluster <cluster_id> --proposal <proposal_address>")
|
|
.options({
|
|
cluster: {
|
|
type: "string",
|
|
demandOption: true,
|
|
desc: "Multsig Cluster name to check proposal on can be one of [devnet, testnet, mainnet-beta]",
|
|
},
|
|
proposal: {
|
|
type: "string",
|
|
demandOption: true,
|
|
desc: "The proposal address to check",
|
|
},
|
|
});
|
|
|
|
async function main() {
|
|
const argv = await parser.argv;
|
|
const cluster = argv.cluster as PythCluster;
|
|
const squad = SquadsMesh.endpoint(
|
|
getPythClusterApiUrl(cluster),
|
|
new NodeWallet(Keypair.generate()) // dummy wallet
|
|
);
|
|
const transaction = await squad.getTransaction(new PublicKey(argv.proposal));
|
|
const instructions = await getProposalInstructions(squad, transaction);
|
|
const multisigParser = MultisigParser.fromCluster(cluster);
|
|
const parsedInstructions = instructions.map((instruction) => {
|
|
return multisigParser.parseInstruction({
|
|
programId: instruction.programId,
|
|
data: instruction.data as Buffer,
|
|
keys: instruction.keys as AccountMeta[],
|
|
});
|
|
});
|
|
|
|
for (const instruction of parsedInstructions) {
|
|
if (instruction instanceof WormholeMultisigInstruction) {
|
|
if (instruction.governanceAction instanceof EvmSetWormholeAddress) {
|
|
console.log(
|
|
`Verifying EVM set wormhole address on ${instruction.governanceAction.targetChainId}`
|
|
);
|
|
for (const chain of Object.values(DefaultStore.chains)) {
|
|
if (
|
|
chain instanceof EvmChain &&
|
|
chain.wormholeChainName ===
|
|
instruction.governanceAction.targetChainId
|
|
) {
|
|
const address = instruction.governanceAction.address;
|
|
const contract = new WormholeEvmContract(chain, address);
|
|
const currentIndex = await contract.getCurrentGuardianSetIndex();
|
|
const guardianSet = await contract.getGuardianSet();
|
|
|
|
const proxyContract = new EvmContract(chain, address);
|
|
const proxyCode = await proxyContract.getCode();
|
|
const receiverImplementation =
|
|
await proxyContract.getImplementationAddress();
|
|
const implementationCode = await new EvmContract(
|
|
chain,
|
|
receiverImplementation
|
|
).getCode();
|
|
const proxyDigest = Web3.utils.keccak256(proxyCode);
|
|
const implementationDigest =
|
|
Web3.utils.keccak256(implementationCode);
|
|
const guardianSetDigest = Web3.utils.keccak256(
|
|
JSON.stringify(guardianSet)
|
|
);
|
|
console.log(
|
|
`${chain.getId()} Address:\t\t${address}\nproxy digest:\t\t${proxyDigest}\nimplementation digest:\t${implementationDigest} \nguardian set index:\t${currentIndex} \nguardian set:\t\t${guardianSetDigest}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (instruction.governanceAction instanceof EvmUpgradeContract) {
|
|
console.log(
|
|
`Verifying EVM Upgrade Contract on ${instruction.governanceAction.targetChainId}`
|
|
);
|
|
for (const chain of Object.values(DefaultStore.chains)) {
|
|
if (
|
|
chain instanceof EvmChain &&
|
|
chain.isMainnet() === (cluster === "mainnet-beta") &&
|
|
chain.wormholeChainName ===
|
|
instruction.governanceAction.targetChainId
|
|
) {
|
|
const address = instruction.governanceAction.address;
|
|
const contract = new EvmContract(chain, address);
|
|
const code = await contract.getCodeDigestWithoutAddress();
|
|
// this should be the same keccak256 of the deployedCode property generated by truffle
|
|
console.log(`${chain.getId()} Address:${address} digest:${code}`);
|
|
}
|
|
}
|
|
}
|
|
if (instruction.governanceAction instanceof CosmosUpgradeContract) {
|
|
console.log(
|
|
`Verifying Cosmos Upgrade Contract on ${instruction.governanceAction.targetChainId}`
|
|
);
|
|
for (const chain of Object.values(DefaultStore.chains)) {
|
|
if (
|
|
chain instanceof CosmWasmChain &&
|
|
chain.wormholeChainName ===
|
|
instruction.governanceAction.targetChainId
|
|
) {
|
|
const codeId = instruction.governanceAction.codeId;
|
|
const code = await chain.getCode(Number(codeId));
|
|
// this should be the same checksums.txt in our release file
|
|
console.log(
|
|
`${chain.getId()} Code Id:${codeId} digest:${createHash("sha256")
|
|
.update(code)
|
|
.digest("hex")}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|