Skip to content

Commit fb57721

Browse files
committed
fix session validation
1 parent 938da49 commit fb57721

File tree

2 files changed

+72
-25
lines changed

2 files changed

+72
-25
lines changed

programs/portal/src/instructions/transfer.rs

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub struct TransferBurn<'info> {
135135
impl<'info> TransferBurn<'info> {
136136
// Manually validate accounts instead of using anchor constraints
137137
// so that the context can be shared (nested contexts do not support instruction args)
138-
pub fn validate_accounts(&self, args: &TransferArgs) -> Result<(Pubkey, u8)> {
138+
pub fn validate_accounts(&self, args: &TransferArgs) -> Result<u8> {
139139
let inbox_rate_limit = Pubkey::create_program_address(
140140
&[
141141
InboxRateLimit::SEED_PREFIX,
@@ -161,35 +161,27 @@ impl<'info> TransferBurn<'info> {
161161
return err!(ErrorCode::ConstraintAddress);
162162
}
163163

164-
// Owner of the $M token account depends on whether this function
165-
// was called directly or by tranfer_extension_burn.
166-
let session_owner_seed = if self.common.from.owner.eq(self.token_authority.key) {
167-
self.common.payer.key()
168-
} else {
169-
self.common.from.owner.key()
170-
};
171-
172-
let (session_authority, session_authority_bump) = Pubkey::find_program_address(
173-
&[
174-
crate::SESSION_AUTHORITY_SEED,
175-
session_owner_seed.as_ref(),
176-
args.keccak256().as_ref(),
177-
],
178-
&crate::ID,
179-
);
180-
if !self.session_authority.key().eq(&session_authority) {
181-
return err!(ErrorCode::ConstraintAddress);
182-
}
183-
184-
Ok((session_owner_seed, session_authority_bump))
164+
let session_authority_bump = get_session_authority(
165+
self.common.payer.key,
166+
args.amount,
167+
args.recipient_chain,
168+
args.recipient_address,
169+
args.should_queue,
170+
self.session_authority.key,
171+
// We already validated the session in transfer_extension_burn.
172+
// Also, the amount argument is different after converting to $M.
173+
!self.common.from.owner.eq(self.token_authority.key),
174+
)?;
175+
176+
Ok(session_authority_bump)
185177
}
186178
}
187179

188180
pub fn transfer_burn<'info>(
189181
ctx: Context<'_, '_, '_, 'info, TransferBurn<'info>>,
190182
args: TransferArgs,
191183
) -> Result<()> {
192-
let (session_owner_seed, session_authority_bump) = ctx.accounts.validate_accounts(&args)?;
184+
let session_authority_bump = ctx.accounts.validate_accounts(&args)?;
193185

194186
let accs = ctx.accounts;
195187

@@ -245,7 +237,7 @@ pub fn transfer_burn<'info>(
245237
accs.common.mint.decimals,
246238
&[&[
247239
crate::SESSION_AUTHORITY_SEED,
248-
session_owner_seed.as_ref(),
240+
accs.common.payer.key.as_ref(),
249241
args.keccak256().as_ref(),
250242
&[session_authority_bump],
251243
]],
@@ -347,3 +339,35 @@ fn insert_into_outbox(
347339

348340
Ok(())
349341
}
342+
343+
pub fn get_session_authority(
344+
payer: &Pubkey,
345+
amount: u64,
346+
recipient_chain: ChainId,
347+
recipient_address: [u8; 32],
348+
should_queue: bool,
349+
expected: &Pubkey,
350+
validate: bool,
351+
) -> Result<u8> {
352+
let (session_authority, bump) = Pubkey::find_program_address(
353+
&[
354+
crate::SESSION_AUTHORITY_SEED,
355+
payer.as_ref(),
356+
TransferArgs {
357+
amount,
358+
recipient_chain,
359+
recipient_address,
360+
should_queue,
361+
}
362+
.keccak256()
363+
.as_ref(),
364+
],
365+
&crate::ID,
366+
);
367+
368+
if validate && !session_authority.eq(expected) {
369+
return err!(ErrorCode::ConstraintAddress);
370+
}
371+
372+
Ok(bump)
373+
}

programs/portal/src/instructions/transfer_extension.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use ext_swap::{accounts::SwapGlobal, program::ExtSwap};
55

66
use crate::{
77
TransferBurnBumps, __client_accounts_transfer_burn, __cpi_client_accounts_transfer_burn,
8-
instructions::{ext_swap, transfer_burn, TransferArgs, TransferBurn},
8+
instructions::{ext_swap, get_session_authority, transfer_burn, TransferArgs, TransferBurn},
99
ntt_messages::ChainId,
1010
};
1111

@@ -82,6 +82,29 @@ pub fn transfer_extension_burn<'info>(
8282
destination_token: [u8; 32],
8383
should_queue: bool,
8484
) -> Result<()> {
85+
// Derive and validate session authority
86+
get_session_authority(
87+
ctx.accounts.common.common.payer.key,
88+
ext_principal,
89+
recipient_chain,
90+
recipient_address,
91+
should_queue,
92+
ctx.accounts.common.session_authority.key,
93+
true,
94+
)?;
95+
96+
// $M token account should be owned by token authority
97+
if !ctx
98+
.accounts
99+
.common
100+
.common
101+
.from
102+
.owner
103+
.eq(ctx.accounts.common.token_authority.key)
104+
{
105+
return err!(ErrorCode::ConstraintTokenOwner);
106+
}
107+
85108
let m_pre_balance = ctx.accounts.common.common.from.amount;
86109
let token_auth_bump = ctx.bumps.common.token_authority;
87110

0 commit comments

Comments
 (0)