|
| 1 | +use borsh::{BorshDeserialize, BorshSerialize}; |
| 2 | + |
| 3 | +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone)] |
| 4 | +pub struct CrossContractMessage { |
| 5 | + pub sender: [u8; 32], |
| 6 | + pub method_id: u8, |
| 7 | + pub payload: Vec<u8>, |
| 8 | + pub nonce: u64, |
| 9 | +} |
| 10 | + |
| 11 | +#[derive(Debug, PartialEq)] |
| 12 | +pub enum ContractError { |
| 13 | + DeserializationFailed, |
| 14 | + UnknownMethod, |
| 15 | + InvalidPayload(String), |
| 16 | + OverflowDetected, |
| 17 | +} |
| 18 | + |
| 19 | +pub fn handle_cross_contract_message(raw: &[u8]) -> Result<String, ContractError> { |
| 20 | + let msg = CrossContractMessage::try_from_slice(raw) |
| 21 | + .map_err(|_| ContractError::DeserializationFailed)?; |
| 22 | + match msg.method_id { |
| 23 | + 0 => handle_transfer(&msg.payload), |
| 24 | + 1 => handle_query(&msg.payload), |
| 25 | + 2 => handle_callback(&msg.payload), |
| 26 | + _ => Err(ContractError::UnknownMethod), |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +fn handle_transfer(payload: &[u8]) -> Result<String, ContractError> { |
| 31 | + if payload.len() < 8 { |
| 32 | + return Err(ContractError::InvalidPayload("too short".into())); |
| 33 | + } |
| 34 | + let amount = u64::from_le_bytes(payload[0..8].try_into().unwrap()); |
| 35 | + let fee = amount.checked_mul(3).ok_or(ContractError::OverflowDetected)?; |
| 36 | + Ok(format!("transfer: amount={amount}, fee={fee}")) |
| 37 | +} |
| 38 | + |
| 39 | +fn handle_query(payload: &[u8]) -> Result<String, ContractError> { |
| 40 | + let key = std::str::from_utf8(payload) |
| 41 | + .map_err(|_| ContractError::InvalidPayload("invalid utf8".into()))?; |
| 42 | + Ok(format!("query: key={key}")) |
| 43 | +} |
| 44 | + |
| 45 | +fn handle_callback(payload: &[u8]) -> Result<String, ContractError> { |
| 46 | + if payload.is_empty() { |
| 47 | + return Err(ContractError::InvalidPayload("empty callback".into())); |
| 48 | + } |
| 49 | + Ok(format!("callback: {} bytes", payload.len())) |
| 50 | +} |
0 commit comments