Skip to content

Commit 9dbc340

Browse files
authored
fix(svm): use bytes32 for foreign amounts (#1045)
* fix(svm): use bytes32 for foreign amounts Signed-off-by: Reinis Martinsons <[email protected]> * fix: update tests for bytes32 amounts Signed-off-by: Reinis Martinsons <[email protected]> * update scripts for bytes32 amounts Signed-off-by: Reinis Martinsons <[email protected]> * fix: update scripts Signed-off-by: Reinis Martinsons <[email protected]> --------- Signed-off-by: Reinis Martinsons <[email protected]>
1 parent 62ce7d9 commit 9dbc340

25 files changed

+162
-99
lines changed

programs/svm-spoke/src/common/relay_data.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub struct RelayData {
77
pub exclusive_relayer: Pubkey,
88
pub input_token: Pubkey,
99
pub output_token: Pubkey,
10-
pub input_amount: u64,
10+
pub input_amount: [u8; 32],
1111
pub output_amount: u64,
1212
pub origin_chain_id: u64,
1313
pub deposit_id: [u8; 32],

programs/svm-spoke/src/event.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub struct FundsDeposited {
3939
pub input_token: Pubkey,
4040
pub output_token: Pubkey,
4141
pub input_amount: u64,
42-
pub output_amount: u64,
42+
pub output_amount: [u8; 32],
4343
pub destination_chain_id: u64,
4444
pub deposit_id: [u8; 32],
4545
pub quote_timestamp: u32,
@@ -71,7 +71,7 @@ pub struct RelayExecutionEventInfo {
7171
pub struct FilledRelay {
7272
pub input_token: Pubkey,
7373
pub output_token: Pubkey,
74-
pub input_amount: u64,
74+
pub input_amount: [u8; 32],
7575
pub output_amount: u64,
7676
pub repayment_chain_id: u64,
7777
pub origin_chain_id: u64,
@@ -91,7 +91,7 @@ pub struct FilledRelay {
9191
pub struct RequestedSlowFill {
9292
pub input_token: Pubkey,
9393
pub output_token: Pubkey,
94-
pub input_amount: u64,
94+
pub input_amount: [u8; 32],
9595
pub output_amount: u64,
9696
pub origin_chain_id: u64,
9797
pub deposit_id: [u8; 32],

programs/svm-spoke/src/instructions/deposit.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,7 @@ use crate::{
2121

2222
#[event_cpi]
2323
#[derive(Accounts)]
24-
#[instruction(
25-
depositor: Pubkey,
26-
recipient: Pubkey,
27-
input_token: Pubkey,
28-
output_token: Pubkey,
29-
input_amount: u64,
30-
output_amount: u64,
31-
destination_chain_id: u64
32-
)]
24+
#[instruction(depositor: Pubkey, recipient: Pubkey, input_token: Pubkey)]
3325
pub struct Deposit<'info> {
3426
#[account(mut)]
3527
pub signer: Signer<'info>,
@@ -82,7 +74,7 @@ pub fn _deposit(
8274
input_token: Pubkey,
8375
output_token: Pubkey,
8476
input_amount: u64,
85-
output_amount: u64,
77+
output_amount: [u8; 32],
8678
destination_chain_id: u64,
8779
exclusive_relayer: Pubkey,
8880
deposit_id: [u8; 32],
@@ -160,7 +152,7 @@ pub fn deposit(
160152
input_token: Pubkey,
161153
output_token: Pubkey,
162154
input_amount: u64,
163-
output_amount: u64,
155+
output_amount: [u8; 32],
164156
destination_chain_id: u64,
165157
exclusive_relayer: Pubkey,
166158
quote_timestamp: u32,
@@ -212,7 +204,7 @@ pub fn deposit_now(
212204
input_token: Pubkey,
213205
output_token: Pubkey,
214206
input_amount: u64,
215-
output_amount: u64,
207+
output_amount: [u8; 32],
216208
destination_chain_id: u64,
217209
exclusive_relayer: Pubkey,
218210
fill_deadline_offset: u32,
@@ -264,7 +256,7 @@ pub fn unsafe_deposit(
264256
input_token: Pubkey,
265257
output_token: Pubkey,
266258
input_amount: u64,
267-
output_amount: u64,
259+
output_amount: [u8; 32],
268260
destination_chain_id: u64,
269261
exclusive_relayer: Pubkey,
270262
deposit_nonce: u64,

programs/svm-spoke/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ pub mod svm_spoke {
217217
/// amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic
218218
/// challenge window in the HubPool, less a system fee.
219219
/// - output_amount: The amount of output tokens that the relayer will send to the recipient on the destination.
220+
/// This is big-endian encoded as a 32-byte array to match its underlying byte representation on EVM side.
220221
/// - destination_chain_id: The destination chain identifier where the fill should be made.
221222
/// - exclusive_relayer: The relayer that will be exclusively allowed to fill this deposit before the exclusivity
222223
/// deadline timestamp. This must be a valid, non-zero address if the exclusivity deadline is greater than the
@@ -238,7 +239,7 @@ pub mod svm_spoke {
238239
input_token: Pubkey,
239240
output_token: Pubkey,
240241
input_amount: u64,
241-
output_amount: u64,
242+
output_amount: [u8; 32],
242243
destination_chain_id: u64,
243244
exclusive_relayer: Pubkey,
244245
quote_timestamp: u32,
@@ -272,7 +273,7 @@ pub mod svm_spoke {
272273
input_token: Pubkey,
273274
output_token: Pubkey,
274275
input_amount: u64,
275-
output_amount: u64,
276+
output_amount: [u8; 32],
276277
destination_chain_id: u64,
277278
exclusive_relayer: Pubkey,
278279
fill_deadline_offset: u32,
@@ -308,7 +309,7 @@ pub mod svm_spoke {
308309
input_token: Pubkey,
309310
output_token: Pubkey,
310311
input_amount: u64,
311-
output_amount: u64,
312+
output_amount: [u8; 32],
312313
destination_chain_id: u64,
313314
exclusive_relayer: Pubkey,
314315
deposit_nonce: u64,
@@ -391,6 +392,7 @@ pub mod svm_spoke {
391392
/// token on the repayment chain will be sent as a refund to the caller.
392393
/// - output_token: The token that the caller will send to the recipient on this chain.
393394
/// - input_amount: This amount, less a system fee, will be sent to the caller on their repayment chain.
395+
/// This is big-endian encoded as a 32-byte array to match its underlying byte representation on EVM side
394396
/// - output_amount: The amount of output tokens that the caller will send to the recipient.
395397
/// - origin_chain_id: The origin chain identifier.
396398
/// - exclusive_relayer: The relayer that will be exclusively allowed to fill this deposit before the

programs/svm-spoke/src/utils/delegate_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub struct DepositSeedData<'a> {
1313
pub input_token: Pubkey,
1414
pub output_token: Pubkey,
1515
pub input_amount: u64,
16-
pub output_amount: u64,
16+
pub output_amount: [u8; 32],
1717
pub destination_chain_id: u64,
1818
pub exclusive_relayer: Pubkey,
1919
pub quote_timestamp: u32,
@@ -29,7 +29,7 @@ pub struct DepositNowSeedData<'a> {
2929
pub input_token: Pubkey,
3030
pub output_token: Pubkey,
3131
pub input_amount: u64,
32-
pub output_amount: u64,
32+
pub output_amount: [u8; 32],
3333
pub destination_chain_id: u64,
3434
pub exclusive_relayer: Pubkey,
3535
pub fill_deadline_offset: u32,

scripts/svm/closeRelayerPdas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async function closeFillPda(eventData: any, seed: BN): Promise<void> {
6565
exclusiveRelayer: new PublicKey(eventData.exclusiveRelayer),
6666
inputToken: new PublicKey(eventData.inputToken),
6767
outputToken: new PublicKey(eventData.outputToken),
68-
inputAmount: new BN(eventData.inputAmount),
68+
inputAmount: eventData.inputAmount,
6969
outputAmount: new BN(eventData.outputAmount),
7070
originChainId: new BN(eventData.originChainId),
7171
depositId: eventData.depositId,

scripts/svm/fakeFillWithRandomDistribution.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
calculateRelayHashUint8Array,
2121
getFillRelayDelegatePda,
2222
getSpokePoolProgram,
23+
intToU8Array32,
2324
loadFillRelayParams,
2425
sendTransactionWithLookupTable,
2526
} from "../../src/svm/web3-v1";
@@ -40,10 +41,10 @@ const argv = yargs(hideBin(process.argv))
4041
.option("exclusiveRelayer", { type: "string", demandOption: false, describe: "Exclusive relayer public key" })
4142
.option("inputToken", { type: "string", demandOption: true, describe: "Input token public key" })
4243
.option("outputToken", { type: "string", demandOption: true, describe: "Output token public key" })
43-
.option("inputAmount", { type: "number", demandOption: true, describe: "Input amount" })
44+
.option("inputAmount", { type: "string", demandOption: true, describe: "Input amount" })
4445
.option("outputAmount", { type: "number", demandOption: true, describe: "Output amount" })
4546
.option("originChainId", { type: "string", demandOption: true, describe: "Origin chain ID" })
46-
.option("depositId", { type: "array", demandOption: true, describe: "Deposit ID" })
47+
.option("depositId", { type: "string", demandOption: true, describe: "Deposit ID" })
4748
.option("fillDeadline", { type: "number", demandOption: false, describe: "Fill deadline" })
4849
.option("exclusivityDeadline", { type: "number", demandOption: false, describe: "Exclusivity deadline" })
4950
.option("repaymentChain", { type: "number", demandOption: false, description: "Repayment chain ID" })
@@ -58,10 +59,10 @@ async function fillRelayToRandom(): Promise<void> {
5859
const exclusiveRelayer = new PublicKey(resolvedArgv.exclusiveRelayer || PublicKey.default.toString());
5960
const inputToken = new PublicKey(resolvedArgv.inputToken);
6061
const outputToken = new PublicKey(resolvedArgv.outputToken);
61-
const inputAmount = new BN(resolvedArgv.inputAmount);
62+
const inputAmount = intToU8Array32(new BN(resolvedArgv.inputAmount));
6263
const outputAmount = new BN(resolvedArgv.outputAmount);
6364
const originChainId = new BN(resolvedArgv.originChainId);
64-
const depositId = (resolvedArgv.depositId as number[]).map((id) => id); // Ensure depositId is an array of BN
65+
const depositId = intToU8Array32(new BN(resolvedArgv.depositId));
6566
const fillDeadline = resolvedArgv.fillDeadline || Math.floor(Date.now() / 1000) + 60; // Current time + 1 minute
6667
const exclusivityDeadline = resolvedArgv.exclusivityDeadline || Math.floor(Date.now() / 1000) + 30; // Current time + 30 seconds
6768
const repaymentChain = new BN(resolvedArgv.repaymentChain || 1);
@@ -171,11 +172,17 @@ async function fillRelayToRandom(): Promise<void> {
171172
}))
172173
);
173174

174-
// Delegate state PDA to pull relayer tokens.
175+
// Delegate to pull relayer tokens.
176+
const delegatePda = getFillRelayDelegatePda(
177+
relayHashUint8Array,
178+
repaymentChain,
179+
repaymentAddress,
180+
program.programId
181+
).pda;
175182
const approveInstruction = await createApproveCheckedInstruction(
176183
relayerTokenAccount,
177184
outputToken,
178-
statePda,
185+
delegatePda,
179186
signer.publicKey,
180187
BigInt(relayData.outputAmount.toString()),
181188
tokenDecimals,
@@ -199,7 +206,7 @@ async function fillRelayToRandom(): Promise<void> {
199206
const fillAccounts = {
200207
state: statePda,
201208
signer: signer.publicKey,
202-
delegate: getFillRelayDelegatePda(relayHashUint8Array, repaymentChain, repaymentAddress, program.programId).pda,
209+
delegate: delegatePda,
203210
instructionParams,
204211
mint: outputToken,
205212
relayerTokenAccount,

scripts/svm/findFillStatusPdaFromEvent.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ import { PublicKey } from "@solana/web3.js";
2121
import { BN } from "@coral-xyz/anchor";
2222
import yargs from "yargs";
2323
import { hideBin } from "yargs/helpers";
24-
import { calculateRelayEventHashUint8Array, getSpokePoolProgram, evmAddressToPublicKey } from "../../src/svm/web3-v1";
24+
import {
25+
calculateRelayEventHashUint8Array,
26+
getSpokePoolProgram,
27+
evmAddressToPublicKey,
28+
intToU8Array32,
29+
} from "../../src/svm/web3-v1";
2530

2631
// Set up the provider
2732
const provider = anchor.AnchorProvider.env();
@@ -53,7 +58,7 @@ async function findFillStatusPda() {
5358
exclusiveRelayer: convertAddress(resolvedArgv.exclusive_relayer),
5459
inputToken: convertAddress(resolvedArgv.input_token),
5560
outputToken: convertAddress(resolvedArgv.output_token),
56-
inputAmount: new BN(resolvedArgv.input_amount),
61+
inputAmount: intToU8Array32(new BN(resolvedArgv.input_amount)),
5762
outputAmount: new BN(resolvedArgv.output_amount),
5863
originChainId: new BN(resolvedArgv.origin_chain_id),
5964
depositId: parseStringToUint8Array(resolvedArgv.deposit_id),

scripts/svm/nativeDeposit.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ import {
2323
} from "@solana/web3.js";
2424
import yargs from "yargs";
2525
import { hideBin } from "yargs/helpers";
26-
import { getDepositPda, getDepositSeedHash, getSpokePoolProgram, SOLANA_SPOKE_STATE_SEED } from "../../src/svm/web3-v1";
26+
import {
27+
getDepositPda,
28+
getDepositSeedHash,
29+
getSpokePoolProgram,
30+
intToU8Array32,
31+
SOLANA_SPOKE_STATE_SEED,
32+
u8Array32ToInt,
33+
} from "../../src/svm/web3-v1";
2734

2835
// Set up the provider
2936
const provider = AnchorProvider.env();
@@ -37,7 +44,7 @@ const argv = yargs(hideBin(process.argv))
3744
.option("recipient", { type: "string", demandOption: true, describe: "Recipient public key" })
3845
.option("outputToken", { type: "string", demandOption: true, describe: "Output token public key" })
3946
.option("inputAmount", { type: "number", demandOption: true, describe: "Input amount" })
40-
.option("outputAmount", { type: "number", demandOption: true, describe: "Output amount" })
47+
.option("outputAmount", { type: "string", demandOption: true, describe: "Output amount" })
4148
.option("destinationChainId", { type: "string", demandOption: true, describe: "Destination chain ID" })
4249
.option("integratorId", { type: "string", demandOption: false, describe: "integrator ID" }).argv;
4350

@@ -48,7 +55,7 @@ async function nativeDeposit(): Promise<void> {
4855
const inputToken = NATIVE_MINT;
4956
const outputToken = new PublicKey(resolvedArgv.outputToken);
5057
const inputAmount = new BN(resolvedArgv.inputAmount);
51-
const outputAmount = new BN(resolvedArgv.outputAmount);
58+
const outputAmount = intToU8Array32(new BN(resolvedArgv.outputAmount));
5259
const destinationChainId = new BN(resolvedArgv.destinationChainId);
5360
const exclusiveRelayer = PublicKey.default;
5461
const quoteTimestamp = Math.floor(Date.now() / 1000) - 1;
@@ -85,7 +92,7 @@ async function nativeDeposit(): Promise<void> {
8592
{ property: "inputToken", value: inputToken.toString() },
8693
{ property: "outputToken", value: outputToken.toString() },
8794
{ property: "inputAmount", value: inputAmount.toString() },
88-
{ property: "outputAmount", value: outputAmount.toString() },
95+
{ property: "outputAmount", value: u8Array32ToInt(outputAmount).toString() },
8996
{ property: "destinationChainId", value: destinationChainId.toString() },
9097
{ property: "quoteTimestamp", value: quoteTimestamp.toString() },
9198
{ property: "fillDeadline", value: fillDeadline.toString() },

scripts/svm/queryEvents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async function queryEvents(): Promise<void> {
4141
const eventName = argv.eventName || "any";
4242
const events = await readProgramEvents(provider.connection, program, "confirmed");
4343
const filteredEvents = events.filter((event) => (eventName == "any" ? true : event.name == eventName));
44-
const formattedEvents = filteredEvents.map((event) => stringifyCpiEvent(event));
44+
const formattedEvents = filteredEvents.map((event) => stringifyCpiEvent(event.data, event.name));
4545
console.log(JSON.stringify(formattedEvents, null, 2));
4646
}
4747

0 commit comments

Comments
 (0)