Skip to content

Commit 98fbba2

Browse files
authored
Add check wormhole chain id (#222)
1 parent 2ad5093 commit 98fbba2

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

solana/programs/staking/src/error.rs

+2
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,6 @@ pub enum MessageExecutorError {
159159
VaaNotFinalized,
160160
#[msg("Missing Remaining account")]
161161
MissedRemainingAccount,
162+
#[msg("Message is not meant for this chain")]
163+
InvalidWormholeChainId,
162164
}

solana/programs/staking/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,12 @@ pub mod staking {
708708
bump: ctx.bumps.message_received,
709709
});
710710

711+
require!(
712+
posted_vaa.payload.1.wormhole_chain_id.clone()
713+
== ctx.accounts.message_executor.spoke_chain_id.clone(),
714+
MessageExecutorError::InvalidWormholeChainId
715+
);
716+
711717
// Execute the instructions in the message.
712718
for instruction in posted_vaa.payload.1.instructions.clone() {
713719
// Prepare AccountInfo vector for the instruction.

solana/tests/executor.ts

+67-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
import { SolanaSendSigner } from "@wormhole-foundation/sdk-solana";
3232
import { signAndSendWait } from "@wormhole-foundation/sdk-connect";
3333
import { Chain, contracts } from "@wormhole-foundation/sdk-base";
34-
import { Program, utils } from "@coral-xyz/anchor";
34+
import { AnchorError, Program, utils } from "@coral-xyz/anchor";
3535
import { ExternalProgram } from "./artifacts/external_program.ts";
3636
import externalProgramIdl from "./artifacts/external_program.json";
3737
import BN from "bn.js";
@@ -72,6 +72,17 @@ describe("receive_message", () => {
7272
let messageExecutor: PublicKey;
7373
let externalProgram: Program<ExternalProgram>;
7474

75+
const confirm = async (signature: string): Promise<string> => {
76+
const block =
77+
await stakeConnection.provider.connection.getLatestBlockhash();
78+
await stakeConnection.provider.connection.confirmTransaction({
79+
signature,
80+
...block,
81+
});
82+
83+
return signature;
84+
};
85+
7586
before(async () => {
7687
// Read the Anchor configuration from the specified path
7788
const config = readAnchorConfig(ANCHOR_CONFIG_PATH);
@@ -141,6 +152,60 @@ describe("receive_message", () => {
141152
controller.abort();
142153
});
143154

155+
it("should fail if invalid wormhole chain id", async () => {
156+
const { messagePayloadBuffer, remainingAccounts } =
157+
await generateTransferInstruction(stakeConnection, payer, BigInt(2));
158+
159+
// Generate the VAA
160+
const { publicKey, hash } = await postReceiveMessageVaa(
161+
stakeConnection.provider.connection,
162+
payer,
163+
MOCK_GUARDIANS,
164+
Array.from(Buffer.alloc(32, "f0", "hex")),
165+
BigInt(1),
166+
messagePayloadBuffer,
167+
{ sourceChain: "Ethereum" },
168+
);
169+
170+
// Prepare the seeds
171+
const messageReceivedSeed = Buffer.from("message_received");
172+
const emitterChainSeed = Buffer.alloc(2);
173+
emitterChainSeed.writeUInt16BE(2, 0);
174+
const emitterAddressSeed = Buffer.alloc(32, "f0", "hex");
175+
const sequenceSeed = Buffer.alloc(8);
176+
sequenceSeed.writeBigUInt64BE(BigInt(1), 0);
177+
178+
// Prepare PDA for message_received
179+
const [messageReceivedPDA] = PublicKey.findProgramAddressSync(
180+
[messageReceivedSeed, emitterChainSeed, emitterAddressSeed, sequenceSeed],
181+
stakeConnection.program.programId,
182+
);
183+
184+
try {
185+
await stakeConnection.program.methods
186+
.receiveMessage()
187+
.accounts({
188+
payer: payer.publicKey,
189+
messageReceived: messageReceivedPDA,
190+
airlock: airlockPDA,
191+
messageExecutor: messageExecutorPDA,
192+
postedVaa: publicKey,
193+
wormholeProgram: CORE_BRIDGE_PID,
194+
systemProgram: SystemProgram.programId,
195+
})
196+
.remainingAccounts(remainingAccounts)
197+
.signers([payer])
198+
.rpc()
199+
.then(confirm);
200+
201+
assert.fail("Expected error was not thrown");
202+
} catch (e) {
203+
assert(
204+
(e as AnchorError).error?.errorCode?.code === "InvalidWormholeChainId",
205+
);
206+
}
207+
});
208+
144209
it("should process receive_message correctly", async () => {
145210
const { messagePayloadBuffer, remainingAccounts } =
146211
await generateTransferInstruction(stakeConnection, payer);
@@ -467,6 +532,7 @@ describe("receive_message", () => {
467532
export async function generateTransferInstruction(
468533
stakeConnection: StakeConnection,
469534
payer: Keypair,
535+
wormholeChainId: bigint = BigInt(1),
470536
): Promise<{ messagePayloadBuffer: Buffer; remainingAccounts: any[] }> {
471537
const recipientKeypair = Keypair.generate();
472538
const lamportsForRecipient =
@@ -511,7 +577,6 @@ export async function generateTransferInstruction(
511577

512578
// Prepare the message
513579
const messageId = BigInt(1);
514-
const wormholeChainId = BigInt(1);
515580
const instructions = [instructionData];
516581

517582
// Prepare the message without instructionsLength

0 commit comments

Comments
 (0)