1use super::ink::Gas;
2use crate::{error::StylusError, ink::Ink};
3
4#[derive(Clone, Copy, Debug)]
6pub struct StylusConfig {
7 pub version: u16,
9 pub max_depth: u32,
11 pub pricing: PricingParams,
13}
14
15impl Default for StylusConfig {
16 fn default() -> Self {
17 Self {
18 version: 0,
19 max_depth: u32::MAX,
20 pricing: PricingParams::default(),
21 }
22 }
23}
24
25impl StylusConfig {
26 pub const fn new(version: u16, max_depth: u32, ink_price: u32) -> Self {
27 Self {
28 version,
29 max_depth,
30 pricing: PricingParams::new(ink_price),
31 }
32 }
33}
34
35#[derive(Clone, Copy, Debug)]
37pub struct PricingParams {
38 pub ink_price: u32,
40}
41
42impl Default for PricingParams {
43 fn default() -> Self {
44 Self { ink_price: 1 }
45 }
46}
47
48impl PricingParams {
49 pub const fn new(ink_price: u32) -> Self {
50 Self { ink_price }
51 }
52
53 pub fn gas_to_ink(&self, gas: Gas) -> Ink {
55 Ink(gas.0.saturating_mul(self.ink_price as u64))
56 }
57
58 pub fn ink_to_gas(&self, ink: Ink) -> Gas {
60 Gas(ink.0 / self.ink_price as u64)
61 }
62}
63
64#[derive(Clone, Debug, Default)]
66pub struct CompileConfig {
67 pub version: u16,
69 pub pricing: CompilePricingParams,
71 pub bounds: CompileMemoryParams,
73 pub debug: CompileDebugParams,
75}
76
77#[derive(Clone, Copy, Debug)]
79pub struct CompileMemoryParams {
80 pub heap_bound: u32,
82 pub max_frame_size: u32,
84 pub max_frame_contention: u16,
86}
87
88impl Default for CompileMemoryParams {
89 fn default() -> Self {
90 Self {
91 heap_bound: u32::MAX / 65536, max_frame_size: u32::MAX,
93 max_frame_contention: u16::MAX,
94 }
95 }
96}
97
98#[derive(Clone, Debug, Default)]
100pub struct CompilePricingParams {
101 pub ink_header_cost: u64,
103 pub memory_fill_ink: u64,
105 pub memory_copy_ink: u64,
107}
108
109#[derive(Clone, Debug, Default)]
111pub struct CompileDebugParams {
112 pub debug_funcs: bool,
114 pub debug_info: bool,
116 pub count_ops: bool,
118}
119
120impl CompileConfig {
121 pub fn version(version: u16, debug_chain: bool) -> Result<Self, StylusError> {
127 let mut config = Self {
128 version,
129 debug: CompileDebugParams {
130 debug_funcs: debug_chain,
131 debug_info: debug_chain,
132 ..Default::default()
133 },
134 ..Default::default()
135 };
136
137 match version {
138 0 => {}
139 1..=3 => {
140 config.bounds.heap_bound = 128; config.bounds.max_frame_size = 10 * 1024;
142 config.bounds.max_frame_contention = 4096;
143 config.pricing = CompilePricingParams {
144 ink_header_cost: 2450,
145 memory_fill_ink: 800 / 8,
146 memory_copy_ink: 800 / 8,
147 };
148 }
149 _ => return Err(StylusError::UnsupportedDictionaryVersion(version)),
150 }
151
152 Ok(config)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn unsupported_version_returns_typed_error() {
162 let err = CompileConfig::version(99, false).expect_err("v99 must be unsupported");
163 assert!(
164 matches!(err, StylusError::UnsupportedDictionaryVersion(99)),
165 "expected UnsupportedDictionaryVersion(99), got {err:?}",
166 );
167 }
168
169 #[test]
170 fn supported_versions_succeed() {
171 for v in 0u16..=3 {
172 let cfg = CompileConfig::version(v, false)
173 .unwrap_or_else(|e| panic!("version {v} must be supported, got {e:?}"));
174 assert_eq!(cfg.version, v);
175 }
176 }
177
178 #[test]
179 fn version_boundary_above_supported_is_rejected() {
180 let err = CompileConfig::version(4, false).expect_err("v4 must be unsupported");
181 assert!(matches!(err, StylusError::UnsupportedDictionaryVersion(4)));
182 }
183}