@@ -23,34 +23,36 @@ pub fn invoke_execute<'a>(
23
23
additional_accounts : & [ AccountInfo < ' a > ] ,
24
24
amount : u64 ,
25
25
) -> ProgramResult {
26
- let validation_pubkey = get_extra_account_metas_address ( mint_info. key , program_id) ;
27
- let validation_info = additional_accounts
28
- . iter ( )
29
- . find ( |& x| * x. key == validation_pubkey)
30
- . ok_or ( TransferHookError :: IncorrectAccount ) ?;
31
26
let mut cpi_instruction = instruction:: execute (
32
27
program_id,
33
28
source_info. key ,
34
29
mint_info. key ,
35
30
destination_info. key ,
36
31
authority_info. key ,
37
- & validation_pubkey,
38
32
amount,
39
33
) ;
40
34
41
- let mut cpi_account_infos = vec ! [
42
- source_info,
43
- mint_info,
44
- destination_info,
45
- authority_info,
46
- validation_info. clone( ) ,
47
- ] ;
48
- ExtraAccountMetaList :: add_to_cpi_instruction :: < instruction:: ExecuteInstruction > (
49
- & mut cpi_instruction,
50
- & mut cpi_account_infos,
51
- & validation_info. try_borrow_data ( ) ?,
52
- additional_accounts,
53
- ) ?;
35
+ let validation_pubkey = get_extra_account_metas_address ( mint_info. key , program_id) ;
36
+
37
+ let mut cpi_account_infos = vec ! [ source_info, mint_info, destination_info, authority_info] ;
38
+
39
+ if let Some ( validation_info) = additional_accounts
40
+ . iter ( )
41
+ . find ( |& x| * x. key == validation_pubkey)
42
+ {
43
+ cpi_instruction
44
+ . accounts
45
+ . push ( AccountMeta :: new_readonly ( validation_pubkey, false ) ) ;
46
+ cpi_account_infos. push ( validation_info. clone ( ) ) ;
47
+
48
+ ExtraAccountMetaList :: add_to_cpi_instruction :: < instruction:: ExecuteInstruction > (
49
+ & mut cpi_instruction,
50
+ & mut cpi_account_infos,
51
+ & validation_info. try_borrow_data ( ) ?,
52
+ additional_accounts,
53
+ ) ?;
54
+ }
55
+
54
56
invoke ( & cpi_instruction, & cpi_account_infos)
55
57
}
56
58
@@ -76,55 +78,60 @@ pub fn add_extra_accounts_for_execute_cpi<'a>(
76
78
additional_accounts : & [ AccountInfo < ' a > ] ,
77
79
) -> ProgramResult {
78
80
let validate_state_pubkey = get_extra_account_metas_address ( mint_info. key , program_id) ;
79
- let validate_state_info = additional_accounts
80
- . iter ( )
81
- . find ( |& x| * x. key == validate_state_pubkey)
82
- . ok_or ( TransferHookError :: IncorrectAccount ) ?;
83
81
84
82
let program_info = additional_accounts
85
83
. iter ( )
86
84
. find ( |& x| x. key == program_id)
87
85
. ok_or ( TransferHookError :: IncorrectAccount ) ?;
88
86
89
- let mut execute_instruction = instruction:: execute (
90
- program_id,
91
- source_info. key ,
92
- mint_info. key ,
93
- destination_info. key ,
94
- authority_info. key ,
95
- & validate_state_pubkey,
96
- amount,
97
- ) ;
98
- let mut execute_account_infos = vec ! [
99
- source_info,
100
- mint_info,
101
- destination_info,
102
- authority_info,
103
- validate_state_info. clone( ) ,
104
- ] ;
105
-
106
- ExtraAccountMetaList :: add_to_cpi_instruction :: < instruction:: ExecuteInstruction > (
107
- & mut execute_instruction,
108
- & mut execute_account_infos,
109
- & validate_state_info. try_borrow_data ( ) ?,
110
- additional_accounts,
111
- ) ?;
112
-
113
- // Add only the extra accounts resolved from the validation state
114
- cpi_instruction
115
- . accounts
116
- . extend_from_slice ( & execute_instruction. accounts [ 5 ..] ) ;
117
- cpi_account_infos. extend_from_slice ( & execute_account_infos[ 5 ..] ) ;
87
+ if let Some ( validate_state_info) = additional_accounts
88
+ . iter ( )
89
+ . find ( |& x| * x. key == validate_state_pubkey)
90
+ {
91
+ let mut execute_instruction = instruction:: execute (
92
+ program_id,
93
+ source_info. key ,
94
+ mint_info. key ,
95
+ destination_info. key ,
96
+ authority_info. key ,
97
+ amount,
98
+ ) ;
99
+ execute_instruction
100
+ . accounts
101
+ . push ( AccountMeta :: new_readonly ( validate_state_pubkey, false ) ) ;
102
+ let mut execute_account_infos = vec ! [
103
+ source_info,
104
+ mint_info,
105
+ destination_info,
106
+ authority_info,
107
+ validate_state_info. clone( ) ,
108
+ ] ;
118
109
119
- // Add the program id and validation state account
110
+ ExtraAccountMetaList :: add_to_cpi_instruction :: < instruction:: ExecuteInstruction > (
111
+ & mut execute_instruction,
112
+ & mut execute_account_infos,
113
+ & validate_state_info. try_borrow_data ( ) ?,
114
+ additional_accounts,
115
+ ) ?;
116
+
117
+ // Add only the extra accounts resolved from the validation state
118
+ cpi_instruction
119
+ . accounts
120
+ . extend_from_slice ( & execute_instruction. accounts [ 5 ..] ) ;
121
+ cpi_account_infos. extend_from_slice ( & execute_account_infos[ 5 ..] ) ;
122
+
123
+ // Add the validation state account
124
+ cpi_instruction
125
+ . accounts
126
+ . push ( AccountMeta :: new_readonly ( validate_state_pubkey, false ) ) ;
127
+ cpi_account_infos. push ( validate_state_info. clone ( ) ) ;
128
+ }
129
+
130
+ // Add the program id
120
131
cpi_instruction
121
132
. accounts
122
133
. push ( AccountMeta :: new_readonly ( * program_id, false ) ) ;
123
- cpi_instruction
124
- . accounts
125
- . push ( AccountMeta :: new_readonly ( validate_state_pubkey, false ) ) ;
126
134
cpi_account_infos. push ( program_info. clone ( ) ) ;
127
- cpi_account_infos. push ( validate_state_info. clone ( ) ) ;
128
135
129
136
Ok ( ( ) )
130
137
}
@@ -368,16 +375,18 @@ mod tests {
368
375
validate_state_account_info. clone( ) ,
369
376
] ;
370
377
371
- // Fail missing validation info from additional account infos
372
- let additional_account_infos_missing_infos = vec ! [
373
- extra_meta_1_account_info. clone( ) ,
374
- extra_meta_2_account_info. clone( ) ,
375
- extra_meta_3_account_info. clone( ) ,
376
- extra_meta_4_account_info. clone( ) ,
377
- // validate state missing
378
- transfer_hook_program_account_info. clone( ) ,
379
- ] ;
380
- assert_eq ! (
378
+ // Allow missing validation info from additional account infos
379
+ {
380
+ let additional_account_infos_missing_infos = vec ! [
381
+ extra_meta_1_account_info. clone( ) ,
382
+ extra_meta_2_account_info. clone( ) ,
383
+ extra_meta_3_account_info. clone( ) ,
384
+ extra_meta_4_account_info. clone( ) ,
385
+ // validate state missing
386
+ transfer_hook_program_account_info. clone( ) ,
387
+ ] ;
388
+ let mut cpi_instruction = cpi_instruction. clone ( ) ;
389
+ let mut cpi_account_infos = cpi_account_infos. clone ( ) ;
381
390
add_extra_accounts_for_execute_cpi (
382
391
& mut cpi_instruction,
383
392
& mut cpi_account_infos,
@@ -387,11 +396,32 @@ mod tests {
387
396
destination_account_info. clone ( ) ,
388
397
authority_account_info. clone ( ) ,
389
398
amount,
390
- & additional_account_infos_missing_infos, // Missing account info
399
+ & additional_account_infos_missing_infos,
391
400
)
392
- . unwrap_err( ) ,
393
- TransferHookError :: IncorrectAccount . into( )
394
- ) ;
401
+ . unwrap ( ) ;
402
+ let check_metas = [
403
+ AccountMeta :: new ( source_pubkey, false ) ,
404
+ AccountMeta :: new_readonly ( mint_pubkey, false ) ,
405
+ AccountMeta :: new ( destination_pubkey, false ) ,
406
+ AccountMeta :: new_readonly ( authority_pubkey, true ) ,
407
+ AccountMeta :: new_readonly ( transfer_hook_program_id, false ) ,
408
+ ] ;
409
+
410
+ let check_account_infos = vec ! [
411
+ source_account_info. clone( ) ,
412
+ mint_account_info. clone( ) ,
413
+ destination_account_info. clone( ) ,
414
+ authority_account_info. clone( ) ,
415
+ transfer_hook_program_account_info. clone( ) ,
416
+ ] ;
417
+
418
+ assert_eq ! ( cpi_instruction. accounts, check_metas) ;
419
+ for ( a, b) in std:: iter:: zip ( cpi_account_infos, check_account_infos) {
420
+ assert_eq ! ( a. key, b. key) ;
421
+ assert_eq ! ( a. is_signer, b. is_signer) ;
422
+ assert_eq ! ( a. is_writable, b. is_writable) ;
423
+ }
424
+ }
395
425
396
426
// Fail missing program info from additional account infos
397
427
let additional_account_infos_missing_infos = vec ! [
@@ -466,8 +496,8 @@ mod tests {
466
496
AccountMeta :: new_readonly ( EXTRA_META_2 , true ) ,
467
497
AccountMeta :: new ( extra_meta_3_pubkey, false ) ,
468
498
AccountMeta :: new ( extra_meta_4_pubkey, false ) ,
469
- AccountMeta :: new_readonly ( transfer_hook_program_id, false ) ,
470
499
AccountMeta :: new_readonly ( validate_state_pubkey, false ) ,
500
+ AccountMeta :: new_readonly ( transfer_hook_program_id, false ) ,
471
501
] ;
472
502
473
503
let check_account_infos = vec ! [
@@ -479,8 +509,8 @@ mod tests {
479
509
extra_meta_2_account_info,
480
510
extra_meta_3_account_info,
481
511
extra_meta_4_account_info,
482
- transfer_hook_program_account_info,
483
512
validate_state_account_info,
513
+ transfer_hook_program_account_info,
484
514
] ;
485
515
486
516
assert_eq ! ( cpi_instruction. accounts, check_metas) ;
0 commit comments