1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//! ABI (Application Binary Interface) helpers for function dispatch and calldata parsing.
//!
//! This module provides utilities for:
//! - Computing function selectors from names
//! - Extracting selectors from calldata
//! - Reading typed values from calldata at specific offsets
//!
//! # Function Selectors
//!
//! TruthLinked uses FNV-1a 32-bit hashing for function selectors (4 bytes).
//! This is deterministic, no-std compatible, and provides good distribution.
//!
//! # Example
//!
//! ```ignore
//! use truthlinked_sdk::abi;
//!
//! // Compute selector for "transfer" function
//! let sel = abi::selector_of("transfer");
//!
//! // Parse selector from calldata
//! let calldata = context::calldata()?;
//! let selector = abi::selector(&calldata)?;
//!
//! // Read arguments
//! let amount = abi::read_u64(&calldata, 4)?;
//! let recipient = abi::read_account(&calldata, 12)?;
//! ```
use crate;
/// Error code for malformed or insufficient calldata.
pub const ERR_BAD_CALLDATA: i32 = 10;
/// Computes a 4-byte function selector from a function name.
///
/// Uses FNV-1a 32-bit hash algorithm for deterministic, no-std-friendly hashing.
/// The selector is returned in little-endian byte order.
///
/// # Arguments
///
/// * `name` - Function name (e.g., "transfer", "increment")
///
/// # Returns
///
/// A 4-byte selector that uniquely identifies the function.
///
/// # Example
///
/// ```ignore
/// let sel = abi::selector_of("transfer");
/// // sel is a deterministic 4-byte array
/// ```
/// Extracts the 4-byte function selector from calldata.
///
/// The selector is expected to be the first 4 bytes of the calldata.
/// Returns an error if calldata is shorter than 4 bytes.
///
/// # Arguments
///
/// * `calldata` - Raw calldata bytes (selector + arguments)
///
/// # Returns
///
/// * `Ok([u8; 4])` - The extracted selector
/// * `Err(Error)` - If calldata is too short
///
/// # Example
///
/// ```ignore
/// let calldata = context::calldata()?;
/// let selector = abi::selector(&calldata)?;
///
/// if selector == abi::selector_of("transfer") {
/// // Handle transfer function
/// }
/// ```
/// Reads a `u64` value from calldata at the specified byte offset.
///
/// Interprets 8 bytes starting at `offset` as a little-endian `u64`.
/// Returns an error if there aren't enough bytes available.
///
/// # Arguments
///
/// * `calldata` - Raw calldata bytes
/// * `offset` - Byte offset where the u64 starts (typically 4+ for arguments after selector)
///
/// # Returns
///
/// * `Ok(u64)` - The decoded value
/// * `Err(Error)` - If offset is out of bounds or calldata is too short
///
/// # Example
///
/// ```ignore
/// let calldata = context::calldata()?;
/// let amount = abi::read_u64(&calldata, 4)?; // Read first argument after selector
/// ```
/// Reads a `u128` value from calldata at the specified byte offset.
///
/// Interprets 16 bytes starting at `offset` as a little-endian `u128`.
/// Useful for reading large token amounts or 128-bit integers.
///
/// # Arguments
///
/// * `calldata` - Raw calldata bytes
/// * `offset` - Byte offset where the u128 starts
///
/// # Returns
///
/// * `Ok(u128)` - The decoded value
/// * `Err(Error)` - If offset is out of bounds or calldata is too short
///
/// # Example
///
/// ```ignore
/// let calldata = context::calldata()?;
/// let token_amount = abi::read_u128(&calldata, 4)?;
/// ```
/// Reads a 32-byte account ID from calldata at the specified byte offset.
///
/// Account IDs in TruthLinked are 32-byte arrays (typically BLAKE3 hashes of public keys).
///
/// # Arguments
///
/// * `calldata` - Raw calldata bytes
/// * `offset` - Byte offset where the account ID starts
///
/// # Returns
///
/// * `Ok([u8; 32])` - The account ID
/// * `Err(Error)` - If offset is out of bounds or calldata is too short
///
/// # Example
///
/// ```ignore
/// let calldata = context::calldata()?;
/// let recipient = abi::read_account(&calldata, 4)?;
/// let sender = context::caller()?;
/// ```