This repository was archived by the owner on Jun 16, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexecute_instruction.rs
More file actions
92 lines (76 loc) · 2.68 KB
/
execute_instruction.rs
File metadata and controls
92 lines (76 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use anchor_lang::prelude::*;
use anchor_lang::solana_program::{program::invoke_signed, sysvar::instructions::ID as IX_ID, instruction::Instruction};
use crate::constants::SMART_WALLET_SEED;
use crate::{ verify_authority, PasskeyExt as _, SmartWalletAuthority, SmartWalletData, VerifyParam, ID};
pub fn execute_instruction(
ctx: Context<Verify>,
verify_param: VerifyParam,
instruction_data: Vec<u8>,
) -> Result<()> {
let smart_wallet_authority = &mut ctx.accounts.smart_wallet_authority;
verify_authority(
0,
&ctx.accounts.ix_sysvar,
&verify_param,
smart_wallet_authority.nonce,
smart_wallet_authority.pubkey,
)?;
let smart_wallet_data = &ctx.accounts.smart_wallet_data;
let seeds: &[&[u8]] = &[SMART_WALLET_SEED, &smart_wallet_data.id.to_le_bytes()];
let seeds_signer = &mut seeds.to_vec();
let binding = [smart_wallet_data.bump];
seeds_signer.push(&binding);
let accounts: Vec<AccountMeta> = ctx
.remaining_accounts
.iter()
.map(|acc| AccountMeta {
pubkey: *acc.key,
is_signer: *acc.key == ctx.accounts.smart_wallet.key(), // check if pubkey equal smart_wallet_pda
is_writable: acc.is_writable,
})
.collect();
// Create instruction
let instruction = Instruction {
program_id: ctx.accounts.cpi_program.key(),
accounts,
data: instruction_data,
};
// Execute the instruction
invoke_signed(&instruction, &ctx.remaining_accounts, &[seeds_signer])?;
// Increment nonce
smart_wallet_authority.nonce += 1;
Ok(())
}
#[derive(Accounts)]
#[instruction(verify_param: VerifyParam)]
pub struct Verify<'info> {
/// CHECK: The address check is needed because otherwise
/// the supplied Sysvar could be anything else.
/// The Instruction Sysvar has not been implemented
/// in the Anchor framework yet, so this is the safe approach.
#[account(address = IX_ID)]
pub ix_sysvar: AccountInfo<'info>,
#[account(
mut,
seeds = [SMART_WALLET_SEED, &smart_wallet_data.id.to_le_bytes()],
bump = smart_wallet_data.bump,
owner = ID,
)]
/// CHECK:
pub smart_wallet: UncheckedAccount<'info>,
#[account(
seeds = [SmartWalletData::PREFIX_SEED, smart_wallet.key().as_ref()],
bump,
owner = ID
)]
pub smart_wallet_data: Account<'info, SmartWalletData>,
#[account(
mut,
seeds = [&verify_param.pubkey.to_hashed_bytes(smart_wallet.key())],
bump,
owner = ID,
)]
pub smart_wallet_authority: Account<'info, SmartWalletAuthority>,
/// CHECK:
pub cpi_program: AccountInfo<'info>,
}