1use eot::*;
10
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12 println!("š„ EOT Gas Analysis Examples\n");
13
14 basic_gas_analysis()?;
16 println!("\n{}", "=".repeat(60));
17
18 dynamic_gas_calculation()?;
20 println!("\n{}", "=".repeat(60));
21
22 analyze_erc20_transfer()?;
24 println!("\n{}", "=".repeat(60));
25
26 fork_comparison_analysis()?;
28 println!("\n{}", "=".repeat(60));
29
30 gas_optimization_analysis()?;
32 println!("\n{}", "=".repeat(60));
33
34 bytecode_efficiency_comparison()?;
36
37 Ok(())
38}
39
40fn basic_gas_analysis() -> Result<(), Box<dyn std::error::Error>> {
42 println!("š Example 1: Basic Gas Analysis");
43
44 let opcodes = vec![
46 0x60, 0x10, 0x60, 0x20, 0x01, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xf3, ];
55
56 use crate::traits::OpcodeAnalysis;
58 let analysis = OpcodeRegistry::analyze_gas_usage(&opcodes, Fork::London);
59
60 println!("Bytecode analysis:");
61 println!(" Total gas: {} gas", analysis.total_gas);
62 println!(" Efficiency score: {}/100", analysis.efficiency_score());
63 println!(" Opcodes analyzed: {}", analysis.breakdown.len());
64
65 println!("\nGas breakdown:");
67 for (opcode, gas_cost) in &analysis.breakdown {
68 println!(" 0x{:02x}: {} gas", opcode, gas_cost);
69 }
70
71 let suggestions = OpcodeRegistry::get_optimization_suggestions(&opcodes, Fork::Shanghai);
73 if !suggestions.is_empty() {
74 println!("\nOptimization suggestions:");
75 for (i, suggestion) in suggestions.iter().enumerate() {
76 println!(" {}. {}", i + 1, suggestion);
77 }
78 }
79
80 match OpcodeRegistry::validate_opcode_sequence(&opcodes, Fork::London) {
82 Ok(()) => println!("\nā
Opcode sequence is valid"),
83 Err(e) => println!("\nā Validation error: {}", e),
84 }
85
86 Ok(())
87}
88
89fn dynamic_gas_calculation() -> Result<(), Box<dyn std::error::Error>> {
91 println!("ā” Example 2: Dynamic Gas Calculation");
92
93 let calculator = DynamicGasCalculator::new(Fork::Berlin);
94
95 let cold_context = ExecutionContext::new();
97 let mut warm_context = ExecutionContext::new();
98
99 let address = [0x12u8; 20]; let storage_key = {
102 let mut key = [0u8; 32]; key[24..32].copy_from_slice(&0x123u64.to_be_bytes()); key
105 };
106 warm_context.mark_storage_accessed(&address, &storage_key);
107
108 println!("SLOAD gas costs (EIP-2929 impact):");
110
111 let cold_cost = calculator.calculate_gas_cost(0x54, &cold_context, &[0x123])?;
112 let warm_cost = calculator.calculate_gas_cost(0x54, &warm_context, &[0x123])?;
113
114 println!(" Cold access: {} gas", cold_cost);
115 println!(" Warm access: {} gas", warm_cost);
116 println!(
117 " Savings from warming: {} gas ({:.1}%)",
118 cold_cost - warm_cost,
119 (cold_cost - warm_cost) as f64 / cold_cost as f64 * 100.0
120 );
121
122 println!("\nMemory expansion costs:");
124 let small_memory = calculator.calculate_gas_cost(0x52, &cold_context, &[32])?; let large_memory = calculator.calculate_gas_cost(0x52, &cold_context, &[10000])?; println!(" Small memory access: {} gas", small_memory);
128 println!(" Large memory access: {} gas", large_memory);
129 println!(
130 " Memory expansion overhead: {} gas",
131 large_memory - small_memory
132 );
133
134 Ok(())
135}
136
137fn analyze_erc20_transfer() -> Result<(), Box<dyn std::error::Error>> {
139 println!("š° Example 3: ERC-20 Transfer Analysis");
140
141 let calculator = DynamicGasCalculator::new(Fork::London);
142
143 let transfer_sequence = vec![
145 (0x54, vec![0x1001]), (0x54, vec![0x1002]), (0x03, vec![]), (0x01, vec![]), (0x55, vec![0x1001, 0x100]), (0x55, vec![0x1002, 0x200]), (0xa1, vec![0x40, 0x20]), ];
153
154 let analysis = calculator.analyze_sequence_gas(&transfer_sequence)?;
155
156 println!("ERC-20 Transfer Gas Analysis:");
157 println!(" Total gas: {} gas", analysis.total_gas);
158 println!(" Base transaction: 21,000 gas");
159 println!(" Transfer logic: {} gas", analysis.total_gas - 21000);
160
161 let expensive_ops = analysis.top_expensive_operations(3);
163 println!("\nMost expensive operations:");
164 for (i, (opcode, cost)) in expensive_ops.iter().enumerate() {
165 let name = match *opcode {
166 0x54 => "SLOAD",
167 0x55 => "SSTORE",
168 0xa1 => "LOG1",
169 _ => "OTHER",
170 };
171 println!(" {}. {}: {} gas", i + 1, name, cost);
172 }
173
174 if !analysis.optimizations.is_empty() {
176 println!("\nOptimization opportunities:");
177 for (i, opt) in analysis.optimizations.iter().enumerate() {
178 println!(" {}. {}", i + 1, opt);
179 }
180 }
181
182 Ok(())
183}
184
185fn fork_comparison_analysis() -> Result<(), Box<dyn std::error::Error>> {
187 println!("š“ Example 4: Fork Comparison & EIP Impact");
188
189 let opcodes_to_compare = vec![
191 (0x54, "SLOAD"),
192 (0x31, "BALANCE"),
193 (0x3b, "EXTCODESIZE"),
194 (0xf1, "CALL"),
195 ];
196
197 let forks = vec![
198 Fork::Istanbul,
199 Fork::Berlin,
200 Fork::London,
201 Fork::Shanghai,
202 Fork::Cancun,
203 ];
204
205 println!("Gas cost evolution across forks:");
206 println!(
207 "{:<12} {:<8} {:<8} {:<8} {:<8} {:<8}",
208 "Opcode", "Istanbul", "Berlin", "London", "Shanghai", "Cancun"
209 );
210 println!("{}", "-".repeat(60));
211
212 for (opcode, name) in opcodes_to_compare {
213 print!("{:<12}", name);
214 for fork in &forks {
215 let calculator = DynamicGasCalculator::new(*fork);
216 let context = ExecutionContext::new();
217
218 match calculator.calculate_gas_cost(opcode, &context, &[0x123]) {
219 Ok(cost) => print!(" {:<8}", cost),
220 Err(_) => print!(" {:<8}", "N/A"),
221 }
222 }
223 println!();
224 }
225
226 println!("\nEIP-2929 Impact Analysis (Istanbul ā Berlin):");
228 use crate::gas::GasComparator;
229 let changes = GasComparator::get_changes_between_forks(Fork::Istanbul, Fork::Berlin);
230
231 for change in changes.iter().take(5) {
232 if let (Some(old), Some(new)) = (change.old_value, change.new_value) {
233 println!(
234 " 0x{:02x}: {} ā {} gas ({:+} gas)",
235 change.opcode,
236 old,
237 new,
238 new as i32 - old as i32
239 );
240 }
241 }
242
243 let report = GasComparator::generate_comparison_report(Fork::Istanbul, Fork::Berlin);
245 println!("\nFork comparison summary:");
246 println!(
247 " Opcodes with gas changes: {}",
248 report.summary.gas_cost_changes
249 );
250 println!(" Gas increases: {}", report.summary.gas_increases);
251 println!(" Gas decreases: {}", report.summary.gas_decreases);
252
253 Ok(())
254}
255
256fn gas_optimization_analysis() -> Result<(), Box<dyn std::error::Error>> {
258 println!("š§ Example 5: Gas Optimization Analysis");
259
260 let original_contract = vec![
262 (0x54, vec![0x100]), (0x01, vec![]), (0x54, vec![0x100]), (0x02, vec![]), (0x54, vec![0x100]), (0x03, vec![]), (0x55, vec![0x200, 0x42]), ];
270
271 let optimized_contract = vec![
273 (0x54, vec![0x100]), (0x80, vec![]), (0x01, vec![]), (0x81, vec![]), (0x02, vec![]), (0x82, vec![]), (0x03, vec![]), (0x55, vec![0x200, 0x42]), ];
282
283 let calculator = DynamicGasCalculator::new(Fork::London);
284
285 let original_analysis = calculator.analyze_sequence_gas(&original_contract)?;
286 let optimized_analysis = calculator.analyze_sequence_gas(&optimized_contract)?;
287
288 println!("Original contract:");
289 println!(" Total gas: {}", original_analysis.total_gas);
290 println!(
291 " Efficiency score: {}",
292 original_analysis.efficiency_score()
293 );
294
295 println!("\nOptimized contract:");
296 println!(" Total gas: {}", optimized_analysis.total_gas);
297 println!(
298 " Efficiency score: {}",
299 optimized_analysis.efficiency_score()
300 );
301
302 let savings = original_analysis.total_gas - optimized_analysis.total_gas;
303 let savings_percent = (savings as f64 / original_analysis.total_gas as f64) * 100.0;
304
305 println!("\nOptimization results:");
306 println!(" Gas saved: {} ({:.1}%)", savings, savings_percent);
307
308 if savings > 0 {
309 println!(" ā
Optimization successful!");
310 } else {
311 println!(" ā Optimization made things worse!");
312 }
313
314 Ok(())
315}
316
317fn bytecode_efficiency_comparison() -> Result<(), Box<dyn std::error::Error>> {
319 println!("āļø Example 6: Bytecode Efficiency Comparison");
320
321 let calculator = DynamicGasCalculator::new(Fork::Shanghai);
322
323 let push_zero_old = vec![(0x60, vec![0])]; let push_zero_new = vec![(0x5f, vec![])]; let iszero_simple = vec![
329 (0x15, vec![]), ];
331 let iszero_complex = vec![
332 (0x80, vec![]), (0x80, vec![]), (0x14, vec![]), (0x15, vec![]), ];
337
338 println!("Efficiency comparison results:");
339
340 let old_push_analysis = calculator.analyze_sequence_gas(&push_zero_old)?;
342 let new_push_analysis = calculator.analyze_sequence_gas(&push_zero_new)?;
343
344 println!("\nPush zero implementations:");
345 println!(" PUSH1 0x00: {} gas", old_push_analysis.total_gas);
346 println!(" PUSH0: {} gas", new_push_analysis.total_gas);
347 println!(
348 " Savings: {} gas",
349 old_push_analysis.total_gas - new_push_analysis.total_gas
350 );
351
352 let simple_analysis = calculator.analyze_sequence_gas(&iszero_simple)?;
354 let complex_analysis = calculator.analyze_sequence_gas(&iszero_complex)?;
355
356 println!("\nZero-check implementations:");
357 println!(
358 " Simple ISZERO: {} gas (efficiency: {}%)",
359 simple_analysis.total_gas,
360 simple_analysis.efficiency_score()
361 );
362 println!(
363 " Complex check: {} gas (efficiency: {}%)",
364 complex_analysis.total_gas,
365 complex_analysis.efficiency_score()
366 );
367
368 println!("\nš General Optimization Recommendations:");
370 println!(" 1. Use PUSH0 instead of PUSH1 0x00 (Shanghai+)");
371 println!(" 2. Avoid redundant DUP operations");
372 println!(" 3. Cache storage reads when accessing the same slot multiple times");
373 println!(" 4. Use events instead of storage for data that doesn't need querying");
374 println!(" 5. Consider using newer opcodes for better efficiency");
375
376 Ok(())
377}