Skip to content

Commit 1940a0b

Browse files
authored
[xc-admin] Add wormhole logic to the crank-executor (#504)
* Add wormhole and fix some bugs * Export WormholeMultisigInstruction * Restore some unrelated parts of the code * Cleanup * Don't change this file
1 parent 1f64ce5 commit 1940a0b

File tree

5 files changed

+85
-15
lines changed

5 files changed

+85
-15
lines changed

governance/xc-admin/package-lock.json

Lines changed: 6 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

governance/xc-admin/packages/crank-executor/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"format": "prettier --write \"src/**/*.ts\""
1919
},
2020
"dependencies": {
21+
"@certusone/wormhole-sdk": "^0.9.9",
2122
"@coral-xyz/anchor": "^0.26.0",
2223
"@pythnetwork/client": "^2.9.0",
2324
"@solana/web3.js": "^1.73.0",

governance/xc-admin/packages/crank-executor/src/index.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
import {
2+
AccountMeta,
23
Commitment,
34
Connection,
45
Keypair,
56
PublicKey,
67
SendTransactionError,
8+
SystemProgram,
79
Transaction,
810
} from "@solana/web3.js";
911
import SquadsMesh, { DEFAULT_MULTISIG_PROGRAM_ID, getIxPDA } from "@sqds/mesh";
1012
import * as fs from "fs";
1113
import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
12-
import { getProposals } from "xc-admin-common";
14+
import {
15+
getProposals,
16+
MultisigParser,
17+
WormholeMultisigInstruction,
18+
} from "xc-admin-common";
1319
import BN from "bn.js";
1420
import { AnchorProvider } from "@project-serum/anchor";
1521
import {
1622
getPythClusterApiUrl,
1723
PythCluster,
1824
} from "@pythnetwork/client/lib/cluster";
25+
import {
26+
deriveFeeCollectorKey,
27+
getWormholeBridgeData,
28+
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
1929

2030
export function envOrErr(env: string): string {
2131
const val = process.env[env];
@@ -42,6 +52,15 @@ async function run() {
4252
wallet: new NodeWallet(KEYPAIR),
4353
multisigProgramId: DEFAULT_MULTISIG_PROGRAM_ID,
4454
});
55+
const multisigParser = MultisigParser.fromCluster(CLUSTER as PythCluster);
56+
const wormholeFee = (
57+
await getWormholeBridgeData(
58+
squad.connection,
59+
multisigParser.wormholeBridgeAddress!,
60+
COMMITMENT
61+
)
62+
).config.fee;
63+
4564
const proposals = await getProposals(squad, VAULT, undefined, "executeReady");
4665
for (const proposal of proposals) {
4766
// If we have previously cancelled because the proposal was failing, don't attempt
@@ -51,7 +70,35 @@ async function run() {
5170
i <= proposal.instructionIndex;
5271
i++
5372
) {
54-
const transaction = new Transaction().add(
73+
const instructionPda = getIxPDA(
74+
proposal.publicKey,
75+
new BN(i),
76+
squad.multisigProgramId
77+
)[0];
78+
const instruction = await squad.getInstruction(instructionPda);
79+
const parsedInstruction = multisigParser.parseInstruction({
80+
programId: instruction.programId,
81+
data: instruction.data as Buffer,
82+
keys: instruction.keys as AccountMeta[],
83+
});
84+
const transaction = new Transaction();
85+
86+
if (
87+
parsedInstruction instanceof WormholeMultisigInstruction &&
88+
parsedInstruction.name == "postMessage"
89+
) {
90+
transaction.add(
91+
SystemProgram.transfer({
92+
lamports: wormholeFee,
93+
toPubkey: deriveFeeCollectorKey(
94+
multisigParser.wormholeBridgeAddress!
95+
),
96+
fromPubkey: squad.wallet.publicKey,
97+
})
98+
);
99+
}
100+
101+
transaction.add(
55102
await squad.buildExecuteInstruction(
56103
proposal.publicKey,
57104
getIxPDA(proposal.publicKey, new BN(i), squad.multisigProgramId)[0]

governance/xc-admin/packages/xc-admin-common/src/multisig_transaction/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,6 @@ export class MultisigParser {
6565
}
6666
}
6767
}
68+
69+
export { WormholeMultisigInstruction } from "./WormholeMultisigInstruction";
70+
export { PythMultisigInstruction } from "./PythMultisigInstruction";

governance/xc-admin/packages/xc-admin-common/src/propose.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ import {
33
PublicKey,
44
Transaction,
55
TransactionInstruction,
6+
SYSVAR_RENT_PUBKEY,
7+
SYSVAR_CLOCK_PUBKEY,
8+
SystemProgram,
69
} from "@solana/web3.js";
710
import { BN } from "bn.js";
811
import { AnchorProvider } from "@project-serum/anchor";
912
import {
1013
createWormholeProgramInterface,
11-
getPostMessageAccounts,
14+
deriveWormholeBridgeDataKey,
15+
deriveEmitterSequenceKey,
16+
deriveFeeCollectorKey,
1217
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
1318
import { ExecutePostedVaa } from "./governance_payload/ExecutePostedVaa";
1419

@@ -36,7 +41,6 @@ export async function proposeInstructions(
3641
): Promise<PublicKey> {
3742
const msAccount = await squad.getMultisig(vault);
3843
let txToSend: Transaction[] = [];
39-
4044
const createProposal = new Transaction().add(
4145
await squad.buildCreateTransaction(
4246
msAccount.publicKey,
@@ -61,7 +65,7 @@ export async function proposeInstructions(
6165
vault,
6266
newProposalAddress,
6367
instructions[i],
64-
i,
68+
i + 1,
6569
wormholeAddress
6670
);
6771
txToSend.push(
@@ -134,7 +138,7 @@ export async function wrapAsRemoteInstruction(
134138
instructionIndex: number,
135139
wormholeAddress: PublicKey
136140
): Promise<SquadInstruction> {
137-
const emitter = squad.getAuthorityPDA(vault, 0);
141+
const emitter = squad.getAuthorityPDA(vault, 1);
138142

139143
const [messagePDA, messagePdaBump] = getIxAuthorityPDA(
140144
proposalAddress,
@@ -156,12 +160,7 @@ export async function wrapAsRemoteInstruction(
156160
instruction,
157161
]).encode();
158162

159-
const accounts = getPostMessageAccounts(
160-
wormholeAddress,
161-
emitter,
162-
emitter,
163-
messagePDA
164-
);
163+
const accounts = getPostMessageAccounts(wormholeAddress, emitter, messagePDA);
165164

166165
return {
167166
instruction: await wormholeProgram.methods
@@ -173,3 +172,20 @@ export async function wrapAsRemoteInstruction(
173172
authorityType: "custom",
174173
};
175174
}
175+
function getPostMessageAccounts(
176+
wormholeAddress: PublicKey,
177+
emitter: PublicKey,
178+
message: PublicKey
179+
) {
180+
return {
181+
bridge: deriveWormholeBridgeDataKey(wormholeAddress),
182+
message,
183+
emitter,
184+
sequence: deriveEmitterSequenceKey(emitter, wormholeAddress),
185+
payer: emitter,
186+
feeCollector: deriveFeeCollectorKey(wormholeAddress),
187+
clock: SYSVAR_CLOCK_PUBKEY,
188+
rent: SYSVAR_RENT_PUBKEY,
189+
systemProgram: SystemProgram.programId,
190+
};
191+
}

0 commit comments

Comments
 (0)