-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathcall_handler_v2.rs
More file actions
128 lines (119 loc) · 3.74 KB
/
call_handler_v2.rs
File metadata and controls
128 lines (119 loc) · 3.74 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use borsh::BorshDeserialize;
use solana_program::{
account_info::AccountInfo,
entrypoint::ProgramResult,
instruction::{AccountMeta, Instruction},
program::invoke_signed,
program_error::ProgramError,
pubkey::Pubkey,
system_program,
};
use crate::{
args::CallHandlerArgs,
ephemeral_balance_seeds_from_payer,
error::{INVALID_ESCROW_OWNER, INVALID_ESCROW_PDA},
processor::utils::loaders::{
load_initialized_validator_fees_vault, load_owned_pda, load_pda,
load_signer,
},
};
/// Calls a handler on user specified program
///
/// Accounts:
/// 0: `[signer]` validator
/// 1: `[]` validator fee vault to verify its registration
/// 2: `[]` destination program of an action
/// 3: `[]` source program of an action
/// 4: `[]` escrow authority account which created escrow account
/// 5: `[writable]` non delegated escrow PDA created from escrow_authority (index 4)
/// 6: `[readonly/writable]` other accounts needed for action
/// 7: `[readonly/writable]` other accounts needed for action
/// 8: ...
///
/// Requirements:
///
/// - escrow account initialized
/// - escrow account not delegated
/// - validator as a caller
///
/// Steps:
/// 1. Verify that signer is a valid registered validator
/// 2. Verify escrow pda exists and not delegated
/// 3. Invoke signed on behalf of escrow pda user specified action
///
/// Usage:
///
/// This instruction is meant to be called via CPI with the owning program signing for the
/// delegated account.
pub fn process_call_handler_v2(
_program_id: &Pubkey,
accounts: &[AccountInfo],
data: &[u8],
) -> ProgramResult {
const OTHER_ACCOUNTS_OFFSET: usize = 6;
let (
[validator, validator_fees_vault, destination_program, source_program, escrow_authority_account, escrow_account],
other_accounts,
) = accounts.split_at(OTHER_ACCOUNTS_OFFSET)
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
let args = CallHandlerArgs::try_from_slice(data)?;
// verify account is a signer
load_signer(validator, "validator")?;
// verify signer is a registered validator
load_initialized_validator_fees_vault(
validator,
validator_fees_vault,
true,
)?;
// verify passed escrow_account derived from escrow authority
let escrow_seeds: &[&[u8]] = ephemeral_balance_seeds_from_payer!(
escrow_authority_account.key,
args.escrow_index
);
let escrow_bump = load_pda(
escrow_account,
escrow_seeds,
&crate::id(),
true,
INVALID_ESCROW_PDA,
)?;
load_owned_pda(
escrow_account,
&system_program::id(),
INVALID_ESCROW_OWNER,
)?;
// deduce necessary accounts for CPI
let (accounts_meta, handler_accounts): (
Vec<AccountMeta>,
Vec<AccountInfo>,
) = other_accounts
.iter()
.chain([source_program, escrow_authority_account, escrow_account])
.filter(|account| account.key != validator.key)
.map(|account| {
(
// We enable only escrow to be a signer
AccountMeta {
pubkey: *account.key,
is_writable: account.is_writable,
is_signer: account.key == escrow_account.key,
},
account.clone(),
)
})
.collect();
let handler_instruction = Instruction {
program_id: *destination_program.key,
data: args.data,
accounts: accounts_meta,
};
let bump_slice = &[escrow_bump];
let escrow_signer_seeds = [escrow_seeds, &[bump_slice]].concat();
invoke_signed(
&handler_instruction,
&handler_accounts,
&[&escrow_signer_seeds],
)
}