1#![allow(clippy::integer_arithmetic)]
2#![deny(missing_docs)]
3extern crate solana_program;
11use arrayref::{array_refs, mut_array_refs};
12use solana_program::{
13 declare_id, entrypoint::MAX_PERMITTED_DATA_INCREASE, entrypoint::SUCCESS,
14 program_error::ProgramError, pubkey::Pubkey,
15};
16use std::{
17 mem::{align_of, size_of},
18 ptr::read,
19 slice::{from_raw_parts, from_raw_parts_mut},
20};
21
22declare_id!("shmFc7FxFPiLQHchdHLMLWAS8yjroAP56dpToM3sHz1");
23
24fn fast_copy(mut src: &[u8], mut dst: &mut [u8]) {
26 while src.len() >= 8 {
27 #[allow(clippy::ptr_offset_with_cast)]
28 let (src_word, src_rem) = array_refs![src, 8; ..;];
29 #[allow(clippy::ptr_offset_with_cast)]
30 let (dst_word, dst_rem) = mut_array_refs![dst, 8; ..;];
31 *dst_word = *src_word;
32 src = src_rem;
33 dst = dst_rem;
34 }
35 unsafe {
36 std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
37 }
38}
39
40unsafe fn deserialize_input_parameters<'a>(
44 input: *mut u8,
45) -> Result<(&'a mut [u8], &'a [u8]), u64> {
46 let num_accounts = read(input as *const u64);
48 if num_accounts == 0 {
49 return Err(ProgramError::NotEnoughAccountKeys.into());
50 } else if num_accounts > 1 {
51 return Err(ProgramError::InvalidArgument.into());
52 }
53
54 let data_len_offset = size_of::<u64>()
56 + size_of::<u8>()
57 + size_of::<u8>()
58 + size_of::<u8>()
59 + size_of::<u8>()
60 + size_of::<u32>()
61 + size_of::<Pubkey>()
62 + size_of::<Pubkey>()
63 + size_of::<u64>();
64
65 let account_data_len = read(input.add(data_len_offset) as *const usize);
66 let data_ptr = input.add(data_len_offset + size_of::<u64>());
67 let account_data = from_raw_parts_mut(data_ptr, account_data_len);
68
69 let instruction_len_offset = account_data_len
71 + MAX_PERMITTED_DATA_INCREASE
72 + (account_data_len as *const u8).align_offset(align_of::<u128>())
73 + size_of::<u64>();
74
75 let instruction_data_len = read(data_ptr.add(instruction_len_offset) as *const usize);
76 let instruction_data = from_raw_parts(
77 data_ptr.add(instruction_len_offset + size_of::<u64>()),
78 instruction_data_len,
79 );
80
81 Ok((account_data, instruction_data))
82}
83
84#[no_mangle]
95pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
96 match deserialize_input_parameters(input) {
97 Ok((account_data, instruction_data)) => {
98 if instruction_data.len() < 8 {
99 return ProgramError::AccountDataTooSmall.into();
100 }
101 #[allow(clippy::ptr_offset_with_cast)]
102 let (offset, content) = array_refs![instruction_data, 8; ..;];
103 let offset = usize::from_le_bytes(*offset);
104 if account_data.len() < offset + content.len() {
105 return ProgramError::AccountDataTooSmall.into();
106 }
107 let data_ptr = account_data.as_mut_ptr() as usize;
108 let data = from_raw_parts_mut((data_ptr + offset) as *mut u8, content.len());
109 fast_copy(content, data);
110 }
111 Err(err) => return err,
112 }
113 SUCCESS
114}