smart_contract/
transaction.rs

1use alloc::{vec, vec::Vec};
2
3use crate::payload::{Readable, Writeable};
4
5#[repr(u8)]
6pub enum TransactionTag {
7    Nop,
8    Transfer,
9    Contract,
10    Stake,
11}
12
13pub trait Transaction: Writeable + Readable + Sized {
14    fn send_transaction(self) {
15        let mut payload = vec![];
16        self.write_to(&mut payload);
17
18        unsafe {
19            crate::sys::_send_transaction(self.tag() as u8, payload.as_ptr(), payload.len());
20        }
21    }
22
23    fn tag(&self) -> TransactionTag;
24}
25
26#[derive(Default)]
27pub struct Transfer {
28    pub destination: [u8; 32],
29    pub amount: u64,
30
31    pub invocation: Option<Invocation>,
32}
33
34#[derive(Default)]
35pub struct Invocation {
36    pub gas_limit: u64,
37    pub gas_deposit: u64,
38    pub func_name: Vec<u8>,
39    pub func_params: Vec<u8>,
40}
41
42impl Writeable for Transfer {
43    fn write_to(&self, buffer: &mut Vec<u8>) {
44        self.destination.write_to(buffer);
45        self.amount.write_to(buffer);
46
47        if let Some(ref invocation) = self.invocation {
48            invocation.gas_limit.write_to(buffer);
49            invocation.gas_deposit.write_to(buffer);
50            invocation.func_name.write_to(buffer);
51            invocation.func_params.write_to(buffer);
52        }
53    }
54}
55
56impl Readable for Transfer {
57    fn read_from(buffer: &[u8], pos: &mut u64) -> Transfer {
58        let mut params = Transfer::default();
59
60        params.destination = <[u8; 32]>::read_from(buffer, pos);
61        params.amount = u64::read_from(buffer, pos);
62
63        if *pos < buffer.len() as u64 {
64            let mut invocation = Invocation::default();
65
66            u64::read_from(buffer, pos); // Read gas limit.
67            u64::read_from(buffer, pos); // Read gas deposit.
68
69            if *pos < buffer.len() as u64 {
70                invocation.func_name = Vec::<u8>::read_from(buffer, pos); // Read function name.
71            }
72            if *pos < buffer.len() as u64 {
73                invocation.func_params = Vec::<u8>::read_from(buffer, pos) // Read function params.
74            }
75            params.invocation = Some(invocation);
76        }
77
78        params
79    }
80}
81
82impl Transaction for Transfer {
83    fn tag(&self) -> TransactionTag {
84        TransactionTag::Transfer
85    }
86}
87
88#[derive(Default)]
89pub struct Contract {
90    pub payload: Vec<u8>,
91    pub code: Vec<u8>,
92}
93
94impl Writeable for Contract {
95    fn write_to(&self, buffer: &mut Vec<u8>) {
96        0u64.write_to(buffer); // Specify an empty gas limit.
97        0u64.write_to(buffer); // Specify an empty gas deposit.
98        self.payload.write_to(buffer);
99        buffer.append(&mut self.code.clone());
100    }
101}
102
103impl Readable for Contract {
104    fn read_from(buffer: &[u8], pos: &mut u64) -> Contract {
105        let mut params = Contract::default();
106
107        u64::read_from(buffer, pos); // Ignore gas limit.
108        u64::read_from(buffer, pos); // Ignore gas deposit.
109        params.payload = Vec::<u8>::read_from(buffer, pos);
110        params.code = buffer[*pos as usize..].to_vec();
111
112        *pos = buffer.len() as u64;
113
114        params
115    }
116}