sealevel_tools/cpi/system_program/
transfer.rs1use crate::{
2 account::system::ID,
3 cpi::{CpiAuthority, CpiInstruction},
4 entrypoint::NoStdAccountInfo,
5};
6
7#[derive(Clone, PartialEq, Eq)]
10pub struct Transfer<'a, 'b: 'a> {
11 pub from: CpiAuthority<'a, 'b>,
12 pub to: &'b NoStdAccountInfo,
13 pub lamports: u64,
14}
15
16impl<'a, 'b: 'a> Transfer<'a, 'b> {
17 #[inline(always)]
19 pub fn into_invoke(self) {
20 let Self { from, to, lamports } = self;
21
22 _invoke_transfer(
23 &from,
24 &CpiAuthority {
25 account: to,
26 signer_seeds: None,
27 },
28 lamports,
29 );
30 }
31}
32
33#[inline(always)]
34pub(super) fn _invoke_transfer(from: &CpiAuthority, to: &CpiAuthority, lamports: u64) {
35 let instruction_data = _serialize_instruction_data(lamports);
36
37 let from_account = from.account;
38 let to_account = to.account;
39
40 CpiInstruction {
41 program_id: &ID,
42 accounts: &[from_account.to_meta_c(), to_account.to_meta_c_signer()],
43 data: &instruction_data,
44 }
45 .invoke_possibly_signed(
46 &[from_account.to_info_c(), to_account.to_info_c()],
47 &[from.signer_seeds, to.signer_seeds],
48 );
49}
50
51const IX_DATA_LEN: usize = {
52 4 + core::mem::size_of::<u64>() };
55
56#[inline(always)]
57fn _serialize_instruction_data(lamports: u64) -> [u8; IX_DATA_LEN] {
58 let mut instruction_data = [0; IX_DATA_LEN];
59
60 instruction_data[0] = 2;
62 instruction_data[4..12].copy_from_slice(&lamports.to_le_bytes());
63
64 instruction_data
65}
66
67#[cfg(test)]
68mod test {
69 use solana_sdk::system_instruction::SystemInstruction;
70
71 use super::*;
72
73 #[test]
74 fn test_serialize_instruction_data() {
75 let lamports = 69;
76
77 let instruction_data = _serialize_instruction_data(lamports);
78
79 assert_eq!(
80 bincode::deserialize::<SystemInstruction>(&instruction_data).unwrap(),
81 SystemInstruction::Transfer { lamports }
82 );
83 }
84}