1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum StackValue {
9 Uint(u64),
11 Bytes(Vec<u8>),
13}
14
15impl StackValue {
16 pub fn uint(value: u64) -> Self {
18 Self::Uint(value)
19 }
20
21 pub fn bytes(value: Vec<u8>) -> Self {
23 Self::Bytes(value)
24 }
25
26 pub fn from_string(s: &str) -> Self {
28 Self::Bytes(s.as_bytes().to_vec())
29 }
30
31 pub fn as_uint(&self) -> Result<u64, crate::error::AvmError> {
33 match self {
34 Self::Uint(val) => Ok(*val),
35 Self::Bytes(_) => Err(crate::error::AvmError::TypeError {
36 expected: "uint".to_string(),
37 actual: "bytes".to_string(),
38 }),
39 }
40 }
41
42 pub fn as_bytes(&self) -> Result<&[u8], crate::error::AvmError> {
44 match self {
45 Self::Bytes(bytes) => Ok(bytes),
46 Self::Uint(_) => Err(crate::error::AvmError::TypeError {
47 expected: "bytes".to_string(),
48 actual: "uint".to_string(),
49 }),
50 }
51 }
52
53 pub fn as_bytes_mut(&mut self) -> Result<&mut Vec<u8>, crate::error::AvmError> {
55 match self {
56 Self::Bytes(bytes) => Ok(bytes),
57 Self::Uint(_) => Err(crate::error::AvmError::TypeError {
58 expected: "bytes".to_string(),
59 actual: "uint".to_string(),
60 }),
61 }
62 }
63
64 pub fn as_bool(&self) -> Result<bool, crate::error::AvmError> {
66 match self {
67 Self::Uint(val) => Ok(*val != 0),
68 Self::Bytes(bytes) => {
69 Ok(!bytes.is_empty() && bytes.iter().any(|&b| b != 0))
71 }
72 }
73 }
74
75 pub fn type_name(&self) -> &'static str {
77 match self {
78 Self::Uint(_) => "uint",
79 Self::Bytes(_) => "bytes",
80 }
81 }
82
83 pub fn is_uint(&self) -> bool {
85 matches!(self, Self::Uint(_))
86 }
87
88 pub fn is_bytes(&self) -> bool {
90 matches!(self, Self::Bytes(_))
91 }
92
93 pub fn uint_or_zero(&self) -> u64 {
95 match self {
96 Self::Uint(val) => *val,
97 Self::Bytes(_) => 0,
98 }
99 }
100}
101
102impl fmt::Display for StackValue {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match self {
105 Self::Uint(val) => write!(f, "{val}"),
106 Self::Bytes(bytes) => {
107 if bytes.iter().all(|&b| b.is_ascii() && !b.is_ascii_control()) {
108 write!(f, "\"{}\"", String::from_utf8_lossy(bytes))
109 } else {
110 write!(f, "0x{}", hex::encode(bytes))
111 }
112 }
113 }
114 }
115}
116
117impl From<u64> for StackValue {
118 fn from(value: u64) -> Self {
119 Self::Uint(value)
120 }
121}
122
123impl From<Vec<u8>> for StackValue {
124 fn from(value: Vec<u8>) -> Self {
125 Self::Bytes(value)
126 }
127}
128
129impl From<&[u8]> for StackValue {
130 fn from(value: &[u8]) -> Self {
131 Self::Bytes(value.to_vec())
132 }
133}
134
135impl From<String> for StackValue {
136 fn from(value: String) -> Self {
137 Self::Bytes(value.into_bytes())
138 }
139}
140
141impl From<&str> for StackValue {
142 fn from(value: &str) -> Self {
143 Self::Bytes(value.as_bytes().to_vec())
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
149pub enum TealValue {
150 Uint(u64),
152 Bytes(Vec<u8>),
154}
155
156impl TealValue {
157 pub fn uint(value: u64) -> Self {
159 Self::Uint(value)
160 }
161
162 pub fn bytes(value: Vec<u8>) -> Self {
164 Self::Bytes(value)
165 }
166
167 pub fn to_stack_value(&self) -> StackValue {
169 match self {
170 Self::Uint(val) => StackValue::Uint(*val),
171 Self::Bytes(bytes) => StackValue::Bytes(bytes.clone()),
172 }
173 }
174
175 pub fn from_stack_value(value: &StackValue) -> Self {
177 match value {
178 StackValue::Uint(val) => Self::Uint(*val),
179 StackValue::Bytes(bytes) => Self::Bytes(bytes.clone()),
180 }
181 }
182}
183
184impl fmt::Display for TealValue {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 match self {
187 Self::Uint(val) => write!(f, "{val}"),
188 Self::Bytes(bytes) => {
189 if bytes.iter().all(|&b| b.is_ascii() && !b.is_ascii_control()) {
190 write!(f, "\"{}\"", String::from_utf8_lossy(bytes))
191 } else {
192 write!(f, "0x{}", hex::encode(bytes))
193 }
194 }
195 }
196 }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
201pub enum TealVersion {
202 V1 = 1,
204 V2 = 2,
206 V3 = 3,
208 V4 = 4,
210 V5 = 5,
212 V6 = 6,
214 V7 = 7,
216 V8 = 8,
218 V9 = 9,
220 V10 = 10,
222 V11 = 11,
224}
225
226impl TealVersion {
227 pub fn from_u8(version: u8) -> Result<Self, crate::error::AvmError> {
229 match version {
230 1 => Ok(Self::V1),
231 2 => Ok(Self::V2),
232 3 => Ok(Self::V3),
233 4 => Ok(Self::V4),
234 5 => Ok(Self::V5),
235 6 => Ok(Self::V6),
236 7 => Ok(Self::V7),
237 8 => Ok(Self::V8),
238 9 => Ok(Self::V9),
239 10 => Ok(Self::V10),
240 11 => Ok(Self::V11),
241 _ => Err(crate::error::AvmError::UnsupportedVersion(version)),
242 }
243 }
244
245 pub fn as_u8(self) -> u8 {
247 self as u8
248 }
249
250 pub const fn latest() -> Self {
252 Self::V11
253 }
254
255 pub fn supports_subroutines(self) -> bool {
257 self >= Self::V4
258 }
259
260 pub fn supports_inner_transactions(self) -> bool {
262 self >= Self::V5
263 }
264
265 pub fn supports_boxes(self) -> bool {
267 self >= Self::V8
268 }
269
270 pub fn supports_advanced_crypto(self) -> bool {
272 self >= Self::V5
273 }
274
275 pub fn supports_extended_box_ops(self) -> bool {
277 self >= Self::V9
278 }
279
280 pub fn supports_elliptic_curve_ops(self) -> bool {
282 self >= Self::V10
283 }
284
285 pub fn supports_mimc_and_block(self) -> bool {
287 self >= Self::V11
288 }
289
290 pub const fn all() -> &'static [Self] {
292 &[
293 Self::V1,
294 Self::V2,
295 Self::V3,
296 Self::V4,
297 Self::V5,
298 Self::V6,
299 Self::V7,
300 Self::V8,
301 Self::V9,
302 Self::V10,
303 Self::V11,
304 ]
305 }
306}
307
308impl fmt::Display for TealVersion {
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 write!(f, "{}", self.as_u8())
311 }
312}
313
314impl Default for TealVersion {
315 fn default() -> Self {
316 Self::latest()
317 }
318}
319
320#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
322pub enum RunMode {
323 Signature,
325 Application,
327}
328
329#[derive(Debug, Clone, Copy, PartialEq, Eq)]
331pub enum TxnField {
332 Sender,
333 Fee,
334 FirstValid,
335 FirstValidTime,
336 LastValid,
337 Note,
338 Lease,
339 Receiver,
340 Amount,
341 CloseRemainderTo,
342 VotePK,
343 SelectionPK,
344 VoteFirst,
345 VoteLast,
346 VoteKeyDilution,
347 Type,
348 TypeEnum,
349 XferAsset,
350 AssetAmount,
351 AssetSender,
352 AssetReceiver,
353 AssetCloseTo,
354 GroupIndex,
355 TxID,
356 ApplicationID,
357 OnCompletion,
358 ApplicationArgs,
359 NumAppArgs,
360 Accounts,
361 NumAccounts,
362 ApprovalProgram,
363 ClearStateProgram,
364 RekeyTo,
365 ConfigAsset,
366 ConfigAssetTotal,
367 ConfigAssetDecimals,
368 ConfigAssetDefaultFrozen,
369 ConfigAssetName,
370 ConfigAssetURL,
371 ConfigAssetMetadataHash,
372 ConfigAssetManager,
373 ConfigAssetReserve,
374 ConfigAssetFreeze,
375 ConfigAssetClawback,
376 FreezeAsset,
377 FreezeAssetAccount,
378 FreezeAssetFrozen,
379 Assets,
380 NumAssets,
381 Applications,
382 NumApplications,
383 GlobalNumUint,
384 GlobalNumByteSlice,
385 LocalNumUint,
386 LocalNumByteSlice,
387 ExtraProgramPages,
388 Nonparticipation,
389 Logs,
390 NumLogs,
391 CreatedAssetID,
392 CreatedApplicationID,
393 LastLog,
394 StateProofPK,
395 ApprovalProgramPages,
396 NumApprovalProgramPages,
397 ClearStateProgramPages,
398 NumClearStateProgramPages,
399}
400
401#[derive(Debug, Clone, Copy, PartialEq, Eq)]
403pub enum GlobalField {
404 MinTxnFee,
405 MinBalance,
406 MaxTxnLife,
407 ZeroAddress,
408 GroupSize,
409 LogicSigVersion,
410 Round,
411 LatestTimestamp,
412 CurrentApplicationID,
413 CreatorAddress,
414 CurrentApplicationAddress,
415 GroupID,
416 OpcodeBudget,
417 CallerApplicationID,
418 CallerApplicationAddress,
419 AssetCreateMinBalance,
420 AssetOptInMinBalance,
421 GenesisHash,
422}