arbos/programs/
types.rs

1use alloy_primitives::{Address, B256};
2
3/// Outcome of executing a Stylus WASM program.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[repr(u8)]
6pub enum UserOutcome {
7    Success = 0,
8    Revert = 1,
9    Failure = 2,
10    OutOfInk = 3,
11    OutOfStack = 4,
12}
13
14impl UserOutcome {
15    /// Convert a raw status byte to a UserOutcome.
16    pub fn from_u8(status: u8) -> Option<Self> {
17        match status {
18            0 => Some(Self::Success),
19            1 => Some(Self::Revert),
20            2 => Some(Self::Failure),
21            3 => Some(Self::OutOfInk),
22            4 => Some(Self::OutOfStack),
23            _ => None,
24        }
25    }
26}
27
28/// Host I/O request types for Stylus WASM programs.
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30#[repr(u32)]
31pub enum RequestType {
32    GetBytes32 = 0,
33    SetTrieSlots = 1,
34    GetTransientBytes32 = 2,
35    SetTransientBytes32 = 3,
36    ContractCall = 4,
37    DelegateCall = 5,
38    StaticCall = 6,
39    Create1 = 7,
40    Create2 = 8,
41    EmitLog = 9,
42    AccountBalance = 10,
43    AccountCode = 11,
44    AccountCodeHash = 12,
45    AddPages = 13,
46    CaptureHostIO = 14,
47}
48
49impl RequestType {
50    /// Convert a raw u32 to a RequestType.
51    pub fn from_u32(val: u32) -> Option<Self> {
52        match val {
53            0 => Some(Self::GetBytes32),
54            1 => Some(Self::SetTrieSlots),
55            2 => Some(Self::GetTransientBytes32),
56            3 => Some(Self::SetTransientBytes32),
57            4 => Some(Self::ContractCall),
58            5 => Some(Self::DelegateCall),
59            6 => Some(Self::StaticCall),
60            7 => Some(Self::Create1),
61            8 => Some(Self::Create2),
62            9 => Some(Self::EmitLog),
63            10 => Some(Self::AccountBalance),
64            11 => Some(Self::AccountCode),
65            12 => Some(Self::AccountCodeHash),
66            13 => Some(Self::AddPages),
67            14 => Some(Self::CaptureHostIO),
68            _ => None,
69        }
70    }
71}
72
73/// EVM context data passed to the Stylus runtime during program execution.
74#[derive(Debug, Clone)]
75pub struct EvmData {
76    pub arbos_version: u64,
77    pub block_basefee: B256,
78    pub chain_id: u64,
79    pub block_coinbase: Address,
80    pub block_gas_limit: u64,
81    pub block_number: u64,
82    pub block_timestamp: u64,
83    pub contract_address: Address,
84    pub module_hash: B256,
85    pub msg_sender: Address,
86    pub msg_value: B256,
87    pub tx_gas_price: B256,
88    pub tx_origin: Address,
89    pub reentrant: u32,
90    pub cached: bool,
91    pub tracing: bool,
92}
93
94/// Parameters passed to the Stylus runtime for program execution.
95#[derive(Debug, Clone, Copy)]
96pub struct ProgParams {
97    pub version: u16,
98    pub max_depth: u32,
99    pub ink_price: u32,
100    pub debug_mode: bool,
101}
102
103/// Result of a Stylus program activation.
104#[derive(Debug, Clone)]
105pub struct ActivationResult {
106    pub module_hash: B256,
107    pub init_gas: u16,
108    pub cached_init_gas: u16,
109    pub asm_estimate: u32,
110    pub footprint: u16,
111}
112
113/// Compute EVM memory expansion cost (matches geth's memory.go).
114pub fn evm_memory_cost(size: u64) -> u64 {
115    let words = to_word_size(size);
116    const MEMORY_GAS: u64 = 3;
117    const QUAD_COEFF_DIV: u64 = 512;
118    let linear_cost = words.saturating_mul(MEMORY_GAS);
119    let square_cost = (words.saturating_mul(words)) / QUAD_COEFF_DIV;
120    linear_cost.saturating_add(square_cost)
121}
122
123/// Round up byte size to 32-byte word count.
124pub fn to_word_size(size: u64) -> u64 {
125    if size > u64::MAX - 31 {
126        return u64::MAX / 32 + 1;
127    }
128    size.div_ceil(32)
129}