solmail_program/instructions/escrow/
confirm.rs1use pinocchio::{
2 account_info::AccountInfo,
3 program_error::ProgramError,
4 pubkey::{find_program_address, Pubkey},
5 ProgramResult,
6};
7
8use crate::{
9 constants::{ESCROW_SEED, ESCROW_VAULT_SEED, ORACLE_PUBKEY, TREASURY_SEED},
10 error::SolMailError,
11 state::escrow::EscrowOrder,
12};
13
14pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
27 if data.len() < 16 {
29 return Err(ProgramError::InvalidInstructionData);
30 }
31
32 let mail_id_low = u64::from_le_bytes(data[0..8].try_into().unwrap());
33 let mail_id_high = u64::from_le_bytes(data[8..16].try_into().unwrap());
34
35 let [oracle, escrow_state, escrow_vault, treasury, _system_program] = accounts else {
37 return Err(ProgramError::NotEnoughAccountKeys);
38 };
39
40 if !oracle.is_signer() {
42 return Err(SolMailError::MissingRequiredSignature.into());
43 }
44
45 if oracle.key().as_ref() != &ORACLE_PUBKEY {
47 return Err(SolMailError::UnauthorizedOracle.into());
48 }
49
50 let mut mail_id_bytes = [0u8; 16];
52 mail_id_bytes[..8].copy_from_slice(&mail_id_low.to_le_bytes());
53 mail_id_bytes[8..].copy_from_slice(&mail_id_high.to_le_bytes());
54
55 let (escrow_pda, _) =
57 find_program_address(&[ESCROW_SEED, &mail_id_bytes], program_id);
58
59 if escrow_state.key() != &escrow_pda {
60 return Err(SolMailError::InvalidPda.into());
61 }
62
63 let escrow_data = unsafe { escrow_state.borrow_mut_data_unchecked() };
65 let escrow = EscrowOrder::from_bytes_mut(escrow_data)?;
66
67 if escrow.delivered {
69 return Err(SolMailError::AlreadyDelivered.into());
70 }
71
72 let (vault_pda, _vault_bump) =
74 find_program_address(&[ESCROW_VAULT_SEED, &mail_id_bytes], program_id);
75
76 if escrow_vault.key() != &vault_pda {
77 return Err(SolMailError::InvalidPda.into());
78 }
79
80 let (treasury_pda, _) = find_program_address(&[TREASURY_SEED], program_id);
82
83 if treasury.key() != &treasury_pda {
84 return Err(SolMailError::InvalidPda.into());
85 }
86
87 escrow.delivered = true;
89
90 let state_data = unsafe { escrow_state.borrow_mut_data_unchecked() };
92 state_data.iter_mut().for_each(|b| *b = 0);
93
94 let vault_lamports = escrow_vault.lamports();
96
97 unsafe {
99 *escrow_vault.borrow_mut_lamports_unchecked() = 0;
100 *treasury.borrow_mut_lamports_unchecked() += vault_lamports;
101 }
102
103 let escrow_lamports = escrow_state.lamports();
105 unsafe {
106 *escrow_state.borrow_mut_lamports_unchecked() = 0;
107 *treasury.borrow_mut_lamports_unchecked() += escrow_lamports;
108 }
109
110 Ok(())
111}