Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions programs/svm-spoke/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub enum CommonError {
DisabledRoute,
#[msg("Invalid quote timestamp!")]
InvalidQuoteTimestamp,
#[msg("Invalid fill deadline!")]
#[msg("Ivalid fill deadline!")]
InvalidFillDeadline,
#[msg("Caller is not the exclusive relayer and exclusivity deadline has not passed!")]
NotExclusiveRelayer,
Expand Down Expand Up @@ -74,8 +74,6 @@ pub enum SvmError {
InvalidProductionSeed,
#[msg("Invalid remaining accounts for ATA creation!")]
InvalidATACreationAccounts,
#[msg("Invalid delegate PDA!")]
InvalidDelegatePda,
}

// CCTP specific errors.
Expand Down
72 changes: 9 additions & 63 deletions programs/svm-spoke/src/instructions/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ use crate::{
error::{CommonError, SvmError},
event::FundsDeposited,
state::{Route, State},
utils::{
derive_seed_hash, get_current_time, get_unsafe_deposit_id, transfer_from, DepositNowSeedData, DepositSeedData,
},
utils::{get_current_time, get_unsafe_deposit_id, transfer_from},
};

#[event_cpi]
Expand All @@ -25,7 +23,7 @@ use crate::{
output_token: Pubkey,
input_amount: u64,
output_amount: u64,
destination_chain_id: u64
destination_chain_id: u64,
)]
pub struct Deposit<'info> {
#[account(mut)]
Expand All @@ -38,9 +36,6 @@ pub struct Deposit<'info> {
)]
pub state: Account<'info, State>,

/// CHECK: PDA derived with seeds ["delegate", seed_hash]; used as a CPI signer.
pub delegate: UncheckedAccount<'info>,

#[account(
seeds = [b"route", input_token.as_ref(), state.seed.to_le_bytes().as_ref(), destination_chain_id.to_le_bytes().as_ref()],
bump,
Expand Down Expand Up @@ -88,14 +83,15 @@ pub fn _deposit(
fill_deadline: u32,
exclusivity_parameter: u32,
message: Vec<u8>,
delegate_seed_hash: [u8; 32],
) -> Result<()> {
let state = &mut ctx.accounts.state;

let current_time = get_current_time(state)?;

if current_time.checked_sub(quote_timestamp).unwrap_or(u32::MAX) > state.deposit_quote_time_buffer {
return err!(CommonError::InvalidQuoteTimestamp);
}

if fill_deadline > current_time + state.fill_deadline_buffer {
return err!(CommonError::InvalidFillDeadline);
}
Expand All @@ -105,20 +101,21 @@ pub fn _deposit(
if exclusivity_deadline <= MAX_EXCLUSIVITY_PERIOD_SECONDS {
exclusivity_deadline += current_time;
}

if exclusive_relayer == Pubkey::default() {
return err!(CommonError::InvalidExclusiveRelayer);
}
}

// Depositor must have delegated input_amount to the delegate PDA
// Depositor must have delegated input_amount to the state PDA.
transfer_from(
&ctx.accounts.depositor_token_account,
&ctx.accounts.vault,
input_amount,
&ctx.accounts.delegate,
state,
ctx.bumps.state,
&ctx.accounts.mint,
&ctx.accounts.token_program,
delegate_seed_hash,
)?;

let mut applied_deposit_id = deposit_id;
Expand Down Expand Up @@ -162,22 +159,6 @@ pub fn deposit(
exclusivity_parameter: u32,
message: Vec<u8>,
) -> Result<()> {
let seed_hash = derive_seed_hash(
&(DepositSeedData {
depositor,
recipient,
input_token,
output_token,
input_amount,
output_amount,
destination_chain_id,
exclusive_relayer,
quote_timestamp,
fill_deadline,
exclusivity_parameter,
message: &message,
}),
);
_deposit(
ctx,
depositor,
Expand All @@ -193,7 +174,6 @@ pub fn deposit(
fill_deadline,
exclusivity_parameter,
message,
seed_hash,
)?;

Ok(())
Expand All @@ -215,22 +195,7 @@ pub fn deposit_now(
) -> Result<()> {
let state = &mut ctx.accounts.state;
let current_time = get_current_time(state)?;
let seed_hash = derive_seed_hash(
&(DepositNowSeedData {
depositor,
recipient,
input_token,
output_token,
input_amount,
output_amount,
destination_chain_id,
exclusive_relayer,
fill_deadline_offset,
exclusivity_period,
message: &message,
}),
);
_deposit(
deposit(
ctx,
depositor,
recipient,
Expand All @@ -240,12 +205,10 @@ pub fn deposit_now(
output_amount,
destination_chain_id,
exclusive_relayer,
ZERO_DEPOSIT_ID, // ZERO_DEPOSIT_ID informs internal function to use state.number_of_deposits as id.
current_time,
current_time + fill_deadline_offset,
exclusivity_period,
message,
seed_hash,
)?;

Ok(())
Expand All @@ -269,22 +232,6 @@ pub fn unsafe_deposit(
) -> Result<()> {
// Calculate the unsafe deposit ID as a [u8; 32]
let deposit_id = get_unsafe_deposit_id(ctx.accounts.signer.key(), depositor, deposit_nonce);
let seed_hash = derive_seed_hash(
&(DepositSeedData {
depositor,
recipient,
input_token,
output_token,
input_amount,
output_amount,
destination_chain_id,
exclusive_relayer,
quote_timestamp,
fill_deadline,
exclusivity_parameter,
message: &message,
}),
);
_deposit(
ctx,
depositor,
Expand All @@ -300,7 +247,6 @@ pub fn unsafe_deposit(
fill_deadline,
exclusivity_parameter,
message,
seed_hash,
)?;

Ok(())
Expand Down
24 changes: 9 additions & 15 deletions programs/svm-spoke/src/instructions/fill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
error::{CommonError, SvmError},
event::{FillType, FilledRelay, RelayExecutionEventInfo},
state::{FillRelayParams, FillStatus, FillStatusAccount, State},
utils::{derive_seed_hash, get_current_time, hash_non_empty_message, invoke_handler, transfer_from, FillSeedData},
utils::{get_current_time, hash_non_empty_message, invoke_handler, transfer_from},
};

#[event_cpi]
Expand All @@ -25,12 +25,13 @@ pub struct FillRelay<'info> {
#[account(mut, seeds = [b"instruction_params", signer.key().as_ref()], bump, close = signer)]
pub instruction_params: Option<Account<'info, FillRelayParams>>,

#[account(seeds = [b"state", state.seed.to_le_bytes().as_ref()], bump)]
#[account(
seeds = [b"state", state.seed.to_le_bytes().as_ref()],
bump,
constraint = !state.paused_fills @ CommonError::FillsArePaused
)]
pub state: Account<'info, State>,

/// CHECK: PDA derived with seeds ["delegate", seed_hash]; used as a CPI signer.
pub delegate: UncheckedAccount<'info>,

#[account(
mint::token_program = token_program,
address = relay_data
Expand Down Expand Up @@ -80,15 +81,10 @@ pub struct FillRelay<'info> {

pub fn fill_relay<'info>(
ctx: Context<'_, '_, '_, 'info, FillRelay<'info>>,
relay_hash: [u8; 32],
relay_data: Option<RelayData>,
repayment_chain_id: Option<u64>,
repayment_address: Option<Pubkey>,
) -> Result<()> {
// This type of constraint normally would be checked in the context, but had to move it here in the handler to avoid
// exceeding maximum stack offset.
require!(!ctx.accounts.state.paused_fills, CommonError::FillsArePaused);

let FillRelayParams { relay_data, repayment_chain_id, repayment_address } =
unwrap_fill_relay_params(relay_data, repayment_chain_id, repayment_address, &ctx.accounts.instruction_params);

Expand Down Expand Up @@ -118,17 +114,15 @@ pub fn fill_relay<'info>(
_ => FillType::FastFill,
};

let seed_hash = derive_seed_hash(&(FillSeedData { relay_hash, repayment_chain_id, repayment_address }));

// Relayer must have delegated output_amount to the delegate PDA
// Relayer must have delegated output_amount to the state PDA
transfer_from(
&ctx.accounts.relayer_token_account,
&ctx.accounts.recipient_token_account,
relay_data.output_amount,
&ctx.accounts.delegate,
state,
ctx.bumps.state,
&ctx.accounts.mint,
&ctx.accounts.token_program,
seed_hash,
)?;

// Update the fill status to Filled, set the relayer and fill deadline
Expand Down
8 changes: 3 additions & 5 deletions programs/svm-spoke/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ pub mod svm_spoke {
/// Authority must be the state.
/// - mint (Account): The mint account for the input token.
/// - token_program (Interface): The token program.
/// - delegate (Account): The account used to delegate the input amount of the input token.
///
/// ### Parameters
/// - depositor: The account credited with the deposit. Can be different from the signer.
Expand Down Expand Up @@ -412,10 +411,9 @@ pub mod svm_spoke {
/// - token_program (Interface): The token program.
/// - associated_token_program (Interface): The associated token program.
/// - system_program (Interface): The system program.
/// - delegate (Account): The account used to delegate the output amount of the output token.
///
/// ### Parameters:
/// - relay_hash: The hash identifying the deposit to be filled. Caller must pass this in. Computed as hash of
/// - _relay_hash: The hash identifying the deposit to be filled. Caller must pass this in. Computed as hash of
/// the flattened relay_data & destination_chain_id.
/// - relay_data: Struct containing all the data needed to identify the deposit to be filled. Should match
/// all the same-named parameters emitted in the origin chain FundsDeposited event.
Expand All @@ -442,12 +440,12 @@ pub mod svm_spoke {
/// is passed, the caller must load them via the instruction_params account.
pub fn fill_relay<'info>(
ctx: Context<'_, '_, '_, 'info, FillRelay<'info>>,
relay_hash: [u8; 32],
_relay_hash: [u8; 32],
relay_data: Option<RelayData>,
repayment_chain_id: Option<u64>,
repayment_address: Option<Pubkey>,
) -> Result<()> {
instructions::fill_relay(ctx, relay_hash, relay_data, repayment_chain_id, repayment_address)
instructions::fill_relay(ctx, relay_data, repayment_chain_id, repayment_address)
}

/// Closes the FillStatusAccount PDA to reclaim relayer rent.
Expand Down
45 changes: 0 additions & 45 deletions programs/svm-spoke/src/utils/delegate_utils.rs

This file was deleted.

2 changes: 0 additions & 2 deletions programs/svm-spoke/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod bitmap_utils;
pub mod cctp_utils;
pub mod delegate_utils;
pub mod deposit_utils;
pub mod merkle_proof_utils;
pub mod message_utils;
Expand All @@ -9,7 +8,6 @@ pub mod transfer_utils;

pub use bitmap_utils::*;
pub use cctp_utils::*;
pub use delegate_utils::*;
pub use deposit_utils::*;
pub use merkle_proof_utils::*;
pub use message_utils::*;
Expand Down
20 changes: 10 additions & 10 deletions programs/svm-spoke/src/utils/transfer_utils.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
use crate::{error::SvmError, program::SvmSpoke};
use anchor_lang::prelude::*;
use anchor_spl::token_interface::{transfer_checked, Mint, TokenAccount, TokenInterface, TransferChecked};

use crate::State;

pub fn transfer_from<'info>(
from: &InterfaceAccount<'info, TokenAccount>,
to: &InterfaceAccount<'info, TokenAccount>,
amount: u64,
delegate: &UncheckedAccount<'info>,
state: &Account<'info, State>,
state_bump: u8,
mint: &InterfaceAccount<'info, Mint>,
token_program: &Interface<'info, TokenInterface>,
delegate_seed_hash: [u8; 32],
) -> Result<()> {
let (pda, bump) = Pubkey::find_program_address(&[b"delegate", &delegate_seed_hash], &SvmSpoke::id());
if pda != delegate.key() {
return err!(SvmError::InvalidDelegatePda);
}
let seeds: &[&[u8]] = &[b"delegate".as_ref(), &delegate_seed_hash, &[bump]];
let signer_seeds: &[&[&[u8]]] = &[seeds];
let transfer_accounts = TransferChecked {
from: from.to_account_info(),
mint: mint.to_account_info(),
to: to.to_account_info(),
authority: delegate.to_account_info(),
authority: state.to_account_info(),
};

let state_seed_bytes = state.seed.to_le_bytes();
let seeds = &[b"state", state_seed_bytes.as_ref(), &[state_bump]];
let signer_seeds = &[&seeds[..]];

let cpi_context = CpiContext::new_with_signer(token_program.to_account_info(), transfer_accounts, signer_seeds);

transfer_checked(cpi_context, amount, mint.decimals)
Expand Down
Loading
Loading