From 62a2bcd4e27fa53c040570fb12951420f51e2e06 Mon Sep 17 00:00:00 2001 From: chrismaree Date: Thu, 31 Oct 2024 14:17:21 +0100 Subject: [PATCH 1/9] WIP Signed-off-by: chrismaree --- .../svm-spoke/src/instructions/deposit.rs | 70 ++++++++++++++++++- programs/svm-spoke/src/lib.rs | 32 ++++++++- test/svm/SvmSpoke.Deposit.ts | 50 ++++++++++++- test/svm/SvmSpoke.common.ts | 8 +-- 4 files changed, 151 insertions(+), 9 deletions(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index ac81bb7db..eff8c5464 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -79,7 +79,7 @@ pub fn deposit_v3( exclusive_relayer: Pubkey, quote_timestamp: u32, fill_deadline: u32, - exclusivity_deadline: u32, + exclusivity_period: u32, message: Vec, ) -> Result<()> { let state = &mut ctx.accounts.state; @@ -121,7 +121,7 @@ pub fn deposit_v3( deposit_id: state.number_of_deposits, quote_timestamp, fill_deadline, - exclusivity_deadline, + exclusivity_deadline: current_time + exclusivity_period, depositor, recipient, exclusive_relayer, @@ -131,4 +131,68 @@ pub fn deposit_v3( Ok(()) } -// TODO: do we need other flavours of deposit? like speed up deposit +pub fn deposit_v3_now( + ctx: Context, + depositor: Pubkey, + recipient: Pubkey, + input_token: Pubkey, + output_token: Pubkey, + input_amount: u64, + output_amount: u64, + destination_chain_id: u64, + exclusive_relayer: Pubkey, + fill_deadline_offset: u32, + exclusivity_period: u32, + message: Vec, +) -> Result<()> { + let state = &mut ctx.accounts.state; + + if !ctx.accounts.route.enabled { + return err!(CommonError::DisabledRoute); + } + + let current_time = get_current_time(state)?; + + let quote_timestamp = current_time; + let fill_deadline = current_time + fill_deadline_offset; + + // TODO: if the deposit quote timestamp is bad it is possible to make this error with a subtraction + // overflow (from devnet testing). add a test to re-create this and fix it such that the error is thrown, + // not caught via overflow. + if current_time - quote_timestamp > state.deposit_quote_time_buffer { + return err!(CommonError::InvalidQuoteTimestamp); + } + + if fill_deadline < current_time || fill_deadline > current_time + state.fill_deadline_buffer { + return err!(CommonError::InvalidFillDeadline); + } + + let transfer_accounts = TransferChecked { + from: ctx.accounts.user_token_account.to_account_info(), + mint: ctx.accounts.mint.to_account_info(), + to: ctx.accounts.vault.to_account_info(), + authority: ctx.accounts.signer.to_account_info(), + }; + let cpi_context = CpiContext::new(ctx.accounts.token_program.to_account_info(), transfer_accounts); + transfer_checked(cpi_context, input_amount, ctx.accounts.mint.decimals)?; + + state.number_of_deposits += 1; // Increment number of deposits + + emit_cpi!(V3FundsDeposited { + input_token, + output_token, + input_amount, + output_amount, + destination_chain_id, + deposit_id: state.number_of_deposits, + quote_timestamp, + fill_deadline, + exclusivity_deadline: current_time + exclusivity_period, + depositor, + recipient, + exclusive_relayer, + message, + }); + + Ok(()) +} diff --git a/programs/svm-spoke/src/lib.rs b/programs/svm-spoke/src/lib.rs index bdd8b94dc..9bc5f7f1d 100644 --- a/programs/svm-spoke/src/lib.rs +++ b/programs/svm-spoke/src/lib.rs @@ -99,7 +99,7 @@ pub mod svm_spoke { instructions::set_cross_domain_admin(ctx, cross_domain_admin) } - // User methods. + // Deposit methods. pub fn deposit_v3( ctx: Context, depositor: Pubkey, @@ -132,6 +132,36 @@ pub mod svm_spoke { ) } + pub fn deposit_v3_now( + ctx: Context, + depositor: Pubkey, + recipient: Pubkey, + input_token: Pubkey, + output_token: Pubkey, + input_amount: u64, + output_amount: u64, + destination_chain_id: u64, + exclusive_relayer: Pubkey, + fill_deadline: u32, + exclusivity_deadline: u32, + message: Vec, + ) -> Result<()> { + instructions::deposit_v3_now( + ctx, + depositor, + recipient, + input_token, + output_token, + input_amount, + output_amount, + destination_chain_id, + exclusive_relayer, + fill_deadline, + exclusivity_deadline, + message, + ) + } + // Relayer methods. pub fn fill_v3_relay( ctx: Context, diff --git a/test/svm/SvmSpoke.Deposit.ts b/test/svm/SvmSpoke.Deposit.ts index 0f693abd0..86cba4d99 100644 --- a/test/svm/SvmSpoke.Deposit.ts +++ b/test/svm/SvmSpoke.Deposit.ts @@ -75,7 +75,7 @@ describe("svm_spoke.deposit", () => { await enableRoute(); }); - it("Deposits tokens via deposit_v3 function and checks balances", async () => { + it.only("Deposits tokens via deposit_v3 function and checks balances", async () => { // Verify vault balance is zero before the deposit let vaultAccount = await getAccount(connection, vault); assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit"); @@ -422,4 +422,52 @@ describe("svm_spoke.deposit", () => { const vaultAccount = await getAccount(connection, vault); assertSE(vaultAccount.amount, 0, "Vault balance should not be changed by the fake route deposit"); }); + + it.only("depositV3Now behaves as deposit but forces the quote timestamp as expected", async () => { + // Set up initial deposit data. Note that this method has a slightly different interface to deposit, using + // fillDeadlineOffset rather than fillDeadline. current chain time is added to fillDeadlineOffset to set the + // fillDeadline for the deposit. exclusivityPeriod operates the same as in standard deposit. + // Equally, depositV3Now does not have `quoteTimestamp`. this is set to the current time from the program. + const fillDeadlineOffset = new BN(60); // 60 seconds offset + + // Execute the deposit_v3_now call. Remove the quoteTimestamp from the depositData as not needed for this method. + + await program.methods + .depositV3Now( + depositData.depositor, + depositData.recipient, + depositData.inputToken, + depositData.outputToken, + depositData.inputAmount, + depositData.outputAmount, + depositData.destinationChainId, + depositData.exclusiveRelayer, + fillDeadlineOffset, + depositData.exclusivityPeriod, + depositData.message + ) + .accounts(depositAccounts) + .signers([depositor]) + .rpc(); + + await new Promise((resolve) => setTimeout(resolve, 500)); + + // Fetch and verify the depositEvent + const events = await readProgramEvents(connection, program); + const event = events.find((event) => event.name === "v3FundsDeposited").data; + + // Verify the event props emitted match the expected values + const currentTime = await getCurrentTime(program, state); + const expectedValues = { + ...depositData, + quoteTimestamp: currentTime, + fillDeadline: currentTime + fillDeadlineOffset.toNumber(), + exclusivityDeadline: currentTime + depositData.exclusivityPeriod.toNumber(), + depositId: "1", + }; + + for (const [key, value] of Object.entries(expectedValues)) { + assertSE(event[key], value, `${key} should match`); + } + }); }); diff --git a/test/svm/SvmSpoke.common.ts b/test/svm/SvmSpoke.common.ts index 8c3b9760e..931caa3aa 100644 --- a/test/svm/SvmSpoke.common.ts +++ b/test/svm/SvmSpoke.common.ts @@ -24,7 +24,7 @@ const inputAmount = new BN(500000); const outputAmount = inputAmount; const quoteTimestamp = new BN(Math.floor(Date.now() / 1000) - 10); // 10 seconds ago. const fillDeadline = new BN(Math.floor(Date.now() / 1000) + 600); // 600 seconds from now. -const exclusivityDeadline = new BN(Math.floor(Date.now() / 1000) + 300); // 300 seconds from now. +const exclusivityPeriod = new BN(300); // 300 seconds. const message = Buffer.from("Test message"); const depositQuoteTimeBuffer = new BN(3600); // 1 hour. const fillDeadlineBuffer = new BN(3600 * 4); // 4 hours. @@ -104,7 +104,7 @@ interface DepositData { exclusiveRelayer: PublicKey; quoteTimestamp: BN; fillDeadline: BN; - exclusivityDeadline: BN; + exclusivityPeriod: BN; message: Buffer; } @@ -141,7 +141,7 @@ export const common = { outputAmount, quoteTimestamp, fillDeadline, - exclusivityDeadline, + exclusivityPeriod, message, depositQuoteTimeBuffer, fillDeadlineBuffer, @@ -163,7 +163,7 @@ export const common = { exclusiveRelayer, quoteTimestamp, fillDeadline, - exclusivityDeadline, + exclusivityPeriod, message, } as DepositData, }; From f0e97d27fb18b05704856aacfa5bb3763e7cc19d Mon Sep 17 00:00:00 2001 From: chrismaree Date: Thu, 31 Oct 2024 15:48:22 +0100 Subject: [PATCH 2/9] WIP Signed-off-by: chrismaree --- programs/svm-spoke/src/instructions/deposit.rs | 6 +----- test/svm/SvmSpoke.Deposit.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index eff8c5464..aa292af56 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -153,15 +153,11 @@ pub fn deposit_v3_now( let current_time = get_current_time(state)?; - let quote_timestamp = current_time; let fill_deadline = current_time + fill_deadline_offset; // TODO: if the deposit quote timestamp is bad it is possible to make this error with a subtraction // overflow (from devnet testing). add a test to re-create this and fix it such that the error is thrown, // not caught via overflow. - if current_time - quote_timestamp > state.deposit_quote_time_buffer { - return err!(CommonError::InvalidQuoteTimestamp); - } if fill_deadline < current_time || fill_deadline > current_time + state.fill_deadline_buffer { return err!(CommonError::InvalidFillDeadline); @@ -185,7 +181,7 @@ pub fn deposit_v3_now( output_amount, destination_chain_id, deposit_id: state.number_of_deposits, - quote_timestamp, + quote_timestamp: current_time, fill_deadline, exclusivity_deadline: current_time + exclusivity_period, depositor, diff --git a/test/svm/SvmSpoke.Deposit.ts b/test/svm/SvmSpoke.Deposit.ts index 86cba4d99..5030ed816 100644 --- a/test/svm/SvmSpoke.Deposit.ts +++ b/test/svm/SvmSpoke.Deposit.ts @@ -129,7 +129,7 @@ describe("svm_spoke.deposit", () => { ); }); - it("Verifies V3FundsDeposited after deposits", async () => { + it.only("Verifies V3FundsDeposited after deposits", async () => { depositData.inputAmount = depositData.inputAmount.add(new BN(69)); // Execute the first deposit_v3 call From 0d08332e42fc056521eec47167f254a7abea4c9d Mon Sep 17 00:00:00 2001 From: chrismaree Date: Fri, 1 Nov 2024 11:50:38 +0100 Subject: [PATCH 3/9] WIP Signed-off-by: chrismaree --- .../svm-spoke/src/instructions/deposit.rs | 16 +--- test/svm/SvmSpoke.Deposit.ts | 73 ++++++++++++++----- test/svm/SvmSpoke.common.ts | 8 +- 3 files changed, 64 insertions(+), 33 deletions(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index aa292af56..7544b68e6 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -17,12 +17,7 @@ use crate::{ output_token: Pubkey, input_amount: u64, output_amount: u64, - destination_chain_id: u64, // TODO: we can remove some of these instructions props - exclusive_relayer: Pubkey, - quote_timestamp: u32, - fill_deadline: u32, - exclusivity_deadline: u32, - message: Vec + destination_chain_id: u64, )] pub struct DepositV3<'info> { #[account(mut)] @@ -90,10 +85,7 @@ pub fn deposit_v3( let current_time = get_current_time(state)?; - // TODO: if the deposit quote timestamp is bad it is possible to make this error with a subtraction - // overflow (from devnet testing). add a test to re-create this and fix it such that the error is thrown, - // not caught via overflow. - if current_time - quote_timestamp > state.deposit_quote_time_buffer { + if current_time.checked_sub(quote_timestamp).unwrap_or(u32::MAX) > state.deposit_quote_time_buffer { return err!(CommonError::InvalidQuoteTimestamp); } @@ -155,10 +147,6 @@ pub fn deposit_v3_now( let fill_deadline = current_time + fill_deadline_offset; - // TODO: if the deposit quote timestamp is bad it is possible to make this error with a subtraction - // overflow (from devnet testing). add a test to re-create this and fix it such that the error is thrown, - // not caught via overflow. - if fill_deadline < current_time || fill_deadline > current_time + state.fill_deadline_buffer { return err!(CommonError::InvalidFillDeadline); } diff --git a/test/svm/SvmSpoke.Deposit.ts b/test/svm/SvmSpoke.Deposit.ts index 5030ed816..2b0e3d27a 100644 --- a/test/svm/SvmSpoke.Deposit.ts +++ b/test/svm/SvmSpoke.Deposit.ts @@ -75,7 +75,38 @@ describe("svm_spoke.deposit", () => { await enableRoute(); }); - it.only("Deposits tokens via deposit_v3 function and checks balances", async () => { + it("Invalid input prop sanitization", async () => { + try { + depositData.quoteTimestamp = new BN(10); + // Execute the deposit_v3 call + let depositDataValues = Object.values(depositData) as DepositDataValues; + await program.methods + .depositV3(...depositDataValues) + .accounts(depositAccounts) + .signers([depositor]) + .rpc(); + assert.fail("Expected InvalidQuoteTimestamp error was not thrown"); + } catch (err: any) { + assert.include(err.toString(), "Error Code: InvalidQuoteTimestamp", "Expected InvalidQuoteTimestamp error"); + } + + try { + const currentTime = await getCurrentTime(program, state); + depositData.quoteTimestamp = new BN(currentTime + 10000); + // Execute the deposit_v3 call + let depositDataValues = Object.values(depositData) as DepositDataValues; + await program.methods + .depositV3(...depositDataValues) + .accounts(depositAccounts) + .signers([depositor]) + .rpc(); + assert.fail("Expected InvalidQuoteTimestamp error was not thrown"); + } catch (err: any) { + console.log(err); + assert.include(err.toString(), "Error Code: InvalidQuoteTimestamp", "Expected InvalidQuoteTimestamp error"); + } + }); + it("Deposits tokens via deposit_v3 function and checks balances", async () => { // Verify vault balance is zero before the deposit let vaultAccount = await getAccount(connection, vault); assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit"); @@ -129,7 +160,7 @@ describe("svm_spoke.deposit", () => { ); }); - it.only("Verifies V3FundsDeposited after deposits", async () => { + it("Verifies V3FundsDeposited after deposits", async () => { depositData.inputAmount = depositData.inputAmount.add(new BN(69)); // Execute the first deposit_v3 call @@ -144,7 +175,13 @@ describe("svm_spoke.deposit", () => { // Fetch and verify the depositEvent let events = await readProgramEvents(connection, program); let event = events.find((event) => event.name === "v3FundsDeposited").data; - const expectedValues1 = { ...depositData, depositId: "1" }; // Verify the event props emitted match the depositData. + const currentTime = await getCurrentTime(program, state); + const { exclusivityPeriod, ...restOfDepositData } = depositData; // Strip exclusivityPeriod from depositData + const expectedValues1 = { + ...restOfDepositData, + depositId: "1", + exclusivityDeadline: currentTime + exclusivityPeriod.toNumber(), + }; // Verify the event props emitted match the depositData. for (const [key, value] of Object.entries(expectedValues1)) { assertSE(event[key], value, `${key} should match`); } @@ -161,7 +198,7 @@ describe("svm_spoke.deposit", () => { events = await readProgramEvents(connection, program); event = events.find((event) => event.name === "v3FundsDeposited" && event.data.depositId.toString() === "2").data; - const expectedValues2 = { ...depositData, depositId: "2" }; // Verify the event props emitted match the depositData. + const expectedValues2 = { ...expectedValues1, depositId: "2" }; // Verify the event props emitted match the depositData. for (const [key, value] of Object.entries(expectedValues2)) { assertSE(event[key], value, `${key} should match`); } @@ -391,8 +428,9 @@ describe("svm_spoke.deposit", () => { // Fetch and verify the depositEvent let events = await readProgramEvents(connection, program); let event = events.find((event) => event.name === "v3FundsDeposited").data; - const expectedValues1 = { ...{ ...depositData, destinationChainId: fakeRouteChainId }, depositId: "1" }; // Verify the event props emitted match the depositData. - for (const [key, value] of Object.entries(expectedValues1)) { + const { exclusivityPeriod, ...restOfDepositData } = depositData; // Strip exclusivityPeriod from depositData + const expectedValues = { ...{ ...restOfDepositData, destinationChainId: fakeRouteChainId }, depositId: "1" }; // Verify the event props emitted match the depositData. + for (const [key, value] of Object.entries(expectedValues)) { assertSE(event[key], value, `${key} should match`); } @@ -423,27 +461,27 @@ describe("svm_spoke.deposit", () => { assertSE(vaultAccount.amount, 0, "Vault balance should not be changed by the fake route deposit"); }); - it.only("depositV3Now behaves as deposit but forces the quote timestamp as expected", async () => { + it("depositV3Now behaves as deposit but forces the quote timestamp as expected", async () => { // Set up initial deposit data. Note that this method has a slightly different interface to deposit, using // fillDeadlineOffset rather than fillDeadline. current chain time is added to fillDeadlineOffset to set the // fillDeadline for the deposit. exclusivityPeriod operates the same as in standard deposit. // Equally, depositV3Now does not have `quoteTimestamp`. this is set to the current time from the program. - const fillDeadlineOffset = new BN(60); // 60 seconds offset + const fillDeadlineOffset = 60; // 60 seconds offset // Execute the deposit_v3_now call. Remove the quoteTimestamp from the depositData as not needed for this method. await program.methods .depositV3Now( - depositData.depositor, - depositData.recipient, - depositData.inputToken, - depositData.outputToken, + depositData.depositor!, + depositData.recipient!, + depositData.inputToken!, + depositData.outputToken!, depositData.inputAmount, depositData.outputAmount, depositData.destinationChainId, - depositData.exclusiveRelayer, + depositData.exclusiveRelayer!, fillDeadlineOffset, - depositData.exclusivityPeriod, + depositData.exclusivityPeriod.toNumber(), depositData.message ) .accounts(depositAccounts) @@ -458,11 +496,12 @@ describe("svm_spoke.deposit", () => { // Verify the event props emitted match the expected values const currentTime = await getCurrentTime(program, state); + const { exclusivityPeriod, ...restOfDepositData } = depositData; // Strip exclusivityPeriod from depositData const expectedValues = { - ...depositData, + ...restOfDepositData, quoteTimestamp: currentTime, - fillDeadline: currentTime + fillDeadlineOffset.toNumber(), - exclusivityDeadline: currentTime + depositData.exclusivityPeriod.toNumber(), + fillDeadline: currentTime + fillDeadlineOffset, + exclusivityDeadline: currentTime + exclusivityPeriod.toNumber(), depositId: "1", }; diff --git a/test/svm/SvmSpoke.common.ts b/test/svm/SvmSpoke.common.ts index 931caa3aa..2ebe04ed2 100644 --- a/test/svm/SvmSpoke.common.ts +++ b/test/svm/SvmSpoke.common.ts @@ -22,7 +22,7 @@ const exclusiveRelayer = Keypair.generate().publicKey; const outputToken = new PublicKey("1111111111113EsMD5n1VA94D2fALdb1SAKLam8j"); // TODO: this is lazy. this is cast USDC from Eth mainnet. const inputAmount = new BN(500000); const outputAmount = inputAmount; -const quoteTimestamp = new BN(Math.floor(Date.now() / 1000) - 10); // 10 seconds ago. +const quoteTimestamp = new BN(Math.floor(Date.now() / 1000) - 50); // 10 seconds ago. const fillDeadline = new BN(Math.floor(Date.now() / 1000) + 600); // 600 seconds from now. const exclusivityPeriod = new BN(300); // 300 seconds. const message = Buffer.from("Test message"); @@ -90,7 +90,11 @@ async function getCurrentTime(program: Program, state: any) { } function assertSE(a: any, b: any, errorMessage: string) { - assert.strictEqual(a.toString(), b.toString(), errorMessage); + if (a === undefined || b === undefined) { + assert.strictEqual(a, b, errorMessage); + } else { + assert.strictEqual(a.toString(), b.toString(), errorMessage); + } } interface DepositData { From 544b7cd363a4e7fcbab40651a89dcb7e5899961e Mon Sep 17 00:00:00 2001 From: chrismaree Date: Fri, 1 Nov 2024 11:54:33 +0100 Subject: [PATCH 4/9] WIP Signed-off-by: chrismaree --- test/svm/SvmSpoke.common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/svm/SvmSpoke.common.ts b/test/svm/SvmSpoke.common.ts index 2ebe04ed2..302cc40cc 100644 --- a/test/svm/SvmSpoke.common.ts +++ b/test/svm/SvmSpoke.common.ts @@ -91,7 +91,7 @@ async function getCurrentTime(program: Program, state: any) { function assertSE(a: any, b: any, errorMessage: string) { if (a === undefined || b === undefined) { - assert.strictEqual(a, b, errorMessage); + throw new Error("Undefined value" + errorMessage); } else { assert.strictEqual(a.toString(), b.toString(), errorMessage); } From 27e5cd300fd1ba8765be520c66b1cde2375bd795 Mon Sep 17 00:00:00 2001 From: chrismaree Date: Fri, 1 Nov 2024 12:34:24 +0100 Subject: [PATCH 5/9] WIP Signed-off-by: chrismaree --- test/svm/SvmSpoke.Deposit.ts | 40 ++---------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/test/svm/SvmSpoke.Deposit.ts b/test/svm/SvmSpoke.Deposit.ts index 5abf0dd60..204547169 100644 --- a/test/svm/SvmSpoke.Deposit.ts +++ b/test/svm/SvmSpoke.Deposit.ts @@ -15,7 +15,7 @@ const { provider, connection, program, owner, seedBalance, initializeState, depo const { createRoutePda, getVaultAta, assertSE, assert, getCurrentTime, depositQuoteTimeBuffer, fillDeadlineBuffer } = common; -describe("svm_spoke.deposit", () => { +describe.only("svm_spoke.deposit", () => { anchor.setProvider(provider); const depositor = Keypair.generate(); @@ -74,38 +74,6 @@ describe("svm_spoke.deposit", () => { await enableRoute(); }); - - it("Invalid input prop sanitization", async () => { - try { - depositData.quoteTimestamp = new BN(10); - // Execute the deposit_v3 call - let depositDataValues = Object.values(depositData) as DepositDataValues; - await program.methods - .depositV3(...depositDataValues) - .accounts(depositAccounts) - .signers([depositor]) - .rpc(); - assert.fail("Expected InvalidQuoteTimestamp error was not thrown"); - } catch (err: any) { - assert.include(err.toString(), "Error Code: InvalidQuoteTimestamp", "Expected InvalidQuoteTimestamp error"); - } - - try { - const currentTime = await getCurrentTime(program, state); - depositData.quoteTimestamp = new BN(currentTime + 10000); - // Execute the deposit_v3 call - let depositDataValues = Object.values(depositData) as DepositDataValues; - await program.methods - .depositV3(...depositDataValues) - .accounts(depositAccounts) - .signers([depositor]) - .rpc(); - assert.fail("Expected InvalidQuoteTimestamp error was not thrown"); - } catch (err: any) { - console.log(err); - assert.include(err.toString(), "Error Code: InvalidQuoteTimestamp", "Expected InvalidQuoteTimestamp error"); - } - }); it("Deposits tokens via deposit_v3 function and checks balances", async () => { // Verify vault balance is zero before the deposit let vaultAccount = await getAccount(connection, vault); @@ -285,11 +253,7 @@ describe("svm_spoke.deposit", () => { .rpc(); assert.fail("Deposit should have failed due to InvalidQuoteTimestamp"); } catch (err: any) { - assert.include( - err.toString(), - "attempt to subtract with overflow", - "Expected underflow error due to future quote timestamp" - ); + assert.include(err.toString(), "Error Code: InvalidQuoteTimestamp", "Expected InvalidQuoteTimestamp error"); } }); From bbf077e73f5c564375625599fc2719d72121c2dc Mon Sep 17 00:00:00 2001 From: chrismaree Date: Fri, 1 Nov 2024 12:34:55 +0100 Subject: [PATCH 6/9] WIP Signed-off-by: chrismaree --- test/svm/SvmSpoke.common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/svm/SvmSpoke.common.ts b/test/svm/SvmSpoke.common.ts index 302cc40cc..b83a13f08 100644 --- a/test/svm/SvmSpoke.common.ts +++ b/test/svm/SvmSpoke.common.ts @@ -22,7 +22,7 @@ const exclusiveRelayer = Keypair.generate().publicKey; const outputToken = new PublicKey("1111111111113EsMD5n1VA94D2fALdb1SAKLam8j"); // TODO: this is lazy. this is cast USDC from Eth mainnet. const inputAmount = new BN(500000); const outputAmount = inputAmount; -const quoteTimestamp = new BN(Math.floor(Date.now() / 1000) - 50); // 10 seconds ago. +const quoteTimestamp = new BN(Math.floor(Date.now() / 1000) - 60); // 60 seconds ago. const fillDeadline = new BN(Math.floor(Date.now() / 1000) + 600); // 600 seconds from now. const exclusivityPeriod = new BN(300); // 300 seconds. const message = Buffer.from("Test message"); From 5c3b2c11c548882c28ee2a79e34e51a4d610c914 Mon Sep 17 00:00:00 2001 From: chrismaree Date: Mon, 4 Nov 2024 10:30:31 +0100 Subject: [PATCH 7/9] WIP Signed-off-by: chrismaree --- .../svm-spoke/src/instructions/deposit.rs | 39 ++++--------------- test/svm/SvmSpoke.Deposit.ts | 2 +- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index 54a4c948d..4ab59a6a5 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -134,45 +134,22 @@ pub fn deposit_v3_now( message: Vec, ) -> Result<()> { let state = &mut ctx.accounts.state; - - if !ctx.accounts.route.enabled { - return err!(CommonError::DisabledRoute); - } - let current_time = get_current_time(state)?; - - let fill_deadline = current_time + fill_deadline_offset; - - if fill_deadline < current_time || fill_deadline > current_time + state.fill_deadline_buffer { - return err!(CommonError::InvalidFillDeadline); - } - - let transfer_accounts = TransferChecked { - from: ctx.accounts.depositor_token_account.to_account_info(), - mint: ctx.accounts.mint.to_account_info(), - to: ctx.accounts.vault.to_account_info(), - authority: ctx.accounts.signer.to_account_info(), - }; - let cpi_context = CpiContext::new(ctx.accounts.token_program.to_account_info(), transfer_accounts); - transfer_checked(cpi_context, input_amount, ctx.accounts.mint.decimals)?; - - state.number_of_deposits += 1; // Increment number of deposits - - emit_cpi!(V3FundsDeposited { + deposit_v3( + ctx, + depositor, + recipient, input_token, output_token, input_amount, output_amount, destination_chain_id, - deposit_id: state.number_of_deposits, - quote_timestamp: current_time, - fill_deadline, - exclusivity_deadline: current_time + exclusivity_period, - depositor, - recipient, exclusive_relayer, + current_time, + current_time + fill_deadline_offset, + exclusivity_period, message, - }); + )?; Ok(()) } diff --git a/test/svm/SvmSpoke.Deposit.ts b/test/svm/SvmSpoke.Deposit.ts index 204547169..b70f32299 100644 --- a/test/svm/SvmSpoke.Deposit.ts +++ b/test/svm/SvmSpoke.Deposit.ts @@ -15,7 +15,7 @@ const { provider, connection, program, owner, seedBalance, initializeState, depo const { createRoutePda, getVaultAta, assertSE, assert, getCurrentTime, depositQuoteTimeBuffer, fillDeadlineBuffer } = common; -describe.only("svm_spoke.deposit", () => { +describe("svm_spoke.deposit", () => { anchor.setProvider(provider); const depositor = Keypair.generate(); From 3c083d14ece22295cb876aa2c1327ce3fd0daf29 Mon Sep 17 00:00:00 2001 From: chrismaree Date: Mon, 4 Nov 2024 10:46:13 +0100 Subject: [PATCH 8/9] WIP Signed-off-by: chrismaree --- programs/svm-spoke/src/instructions/deposit.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index 4ab59a6a5..0b6a3eabc 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -133,8 +133,7 @@ pub fn deposit_v3_now( exclusivity_period: u32, message: Vec, ) -> Result<()> { - let state = &mut ctx.accounts.state; - let current_time = get_current_time(state)?; + let current_time = get_current_time(ctx.accounts.state)?; deposit_v3( ctx, depositor, From 5b8aaf8bb7143013692215a04ca4d299a4b29716 Mon Sep 17 00:00:00 2001 From: chrismaree Date: Mon, 4 Nov 2024 10:47:43 +0100 Subject: [PATCH 9/9] WIP Signed-off-by: chrismaree --- programs/svm-spoke/src/instructions/deposit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/svm-spoke/src/instructions/deposit.rs b/programs/svm-spoke/src/instructions/deposit.rs index 0b6a3eabc..4ab59a6a5 100644 --- a/programs/svm-spoke/src/instructions/deposit.rs +++ b/programs/svm-spoke/src/instructions/deposit.rs @@ -133,7 +133,8 @@ pub fn deposit_v3_now( exclusivity_period: u32, message: Vec, ) -> Result<()> { - let current_time = get_current_time(ctx.accounts.state)?; + let state = &mut ctx.accounts.state; + let current_time = get_current_time(state)?; deposit_v3( ctx, depositor,