@@ -4,7 +4,7 @@ use alloc::{borrow::Cow, boxed::Box, string::String, sync::Arc};
44use alloy_consensus:: transaction:: Either ;
55use alloy_primitives:: {
66 map:: { HashMap , HashSet } ,
7- Address , Bytes ,
7+ Address , Bytes , U256 ,
88} ;
99use revm:: {
1010 context:: { Cfg , ContextTr , LocalContextTr } ,
@@ -146,9 +146,12 @@ impl PrecompilesMap {
146146 Cow :: Owned ( owned) => owned,
147147 } ;
148148
149- for ( addr, precompile_fn) in static_precompiles. inner ( ) {
150- let dyn_precompile: DynPrecompile = ( * precompile_fn) . into ( ) ;
151- dynamic. inner . insert ( * addr, dyn_precompile) ;
149+ for ( addr, precompile_fn) in
150+ static_precompiles. inner ( ) . iter ( ) . map ( |( addr, f) | ( addr, * f) )
151+ {
152+ let precompile =
153+ move |input : PrecompileInput < ' _ > | precompile_fn ( input. data , input. gas ) ;
154+ dynamic. inner . insert ( * addr, precompile. into ( ) ) ;
152155 dynamic. addresses . insert ( * addr) ;
153156 }
154157
@@ -172,7 +175,9 @@ impl PrecompilesMap {
172175 /// Gets a reference to the precompile at the given address.
173176 pub fn get ( & self , address : & Address ) -> Option < impl Precompile + ' _ > {
174177 match self {
175- Self :: Builtin ( precompiles) => precompiles. get ( address) . map ( Either :: Left ) ,
178+ Self :: Builtin ( precompiles) => precompiles
179+ . get ( address)
180+ . map ( |f| Either :: Left ( |input : PrecompileInput < ' _ > | f ( input. data , input. gas ) ) ) ,
176181 Self :: Dynamic ( dyn_precompiles) => dyn_precompiles. inner . get ( address) . map ( Either :: Right ) ,
177182 }
178183 }
@@ -212,11 +217,9 @@ impl<CTX: ContextTr> PrecompileProvider<CTX> for PrecompilesMap {
212217 gas_limit : u64 ,
213218 ) -> Result < Option < InterpreterResult > , String > {
214219 // Get the precompile at the address
215- let precompile = self . get ( address) ;
216-
217- if precompile. is_none ( ) {
220+ let Some ( precompile) = self . get ( address) else {
218221 return Ok ( None ) ;
219- }
222+ } ;
220223
221224 let mut result = InterpreterResult {
222225 result : InstructionResult :: Return ,
@@ -239,8 +242,12 @@ impl<CTX: ContextTr> PrecompileProvider<CTX> for PrecompilesMap {
239242 CallInput :: Bytes ( bytes) => bytes. as_ref ( ) ,
240243 } ;
241244
242- let precompile_result =
243- precompile. expect ( "None case already handled" ) . call ( input_bytes, gas_limit) ;
245+ let precompile_result = precompile. call ( PrecompileInput {
246+ data : input_bytes,
247+ gas : gas_limit,
248+ caller : inputs. caller_address ,
249+ value : inputs. call_value ,
250+ } ) ;
244251
245252 match precompile_result {
246253 Ok ( output) => {
@@ -281,15 +288,6 @@ impl core::fmt::Debug for DynPrecompile {
281288 }
282289}
283290
284- impl < ' a , F > From < F > for DynPrecompile
285- where
286- F : FnOnce ( & ' a [ u8 ] , u64 ) -> PrecompileResult + Precompile + Send + Sync + ' static ,
287- {
288- fn from ( f : F ) -> Self {
289- Self ( Arc :: new ( f) )
290- }
291- }
292-
293291/// A mutable representation of precompiles that allows for runtime modification.
294292///
295293/// This structure stores dynamic precompiles that can be modified at runtime,
@@ -308,38 +306,60 @@ impl core::fmt::Debug for DynPrecompiles {
308306 }
309307}
310308
309+ /// Input for a precompile call.
310+ #[ derive( Debug , Clone ) ]
311+ pub struct PrecompileInput < ' a > {
312+ /// Input data bytes.
313+ pub data : & ' a [ u8 ] ,
314+ /// Gas limit.
315+ pub gas : u64 ,
316+ /// Caller address.
317+ pub caller : Address ,
318+ /// Value sent with the call.
319+ pub value : U256 ,
320+ }
321+
311322/// Trait for implementing precompiled contracts.
312323pub trait Precompile {
313- /// Execute the precompile with the given input data and gas limit.
314- fn call ( & self , data : & [ u8 ] , gas : u64 ) -> PrecompileResult ;
324+ /// Execute the precompile with the given input data, gas limit, and caller address .
325+ fn call ( & self , input : PrecompileInput < ' _ > ) -> PrecompileResult ;
315326}
316327
317328impl < F > Precompile for F
318329where
319- F : Fn ( & [ u8 ] , u64 ) -> PrecompileResult + Send + Sync ,
330+ F : Fn ( PrecompileInput < ' _ > ) -> PrecompileResult + Send + Sync ,
331+ {
332+ fn call ( & self , input : PrecompileInput < ' _ > ) -> PrecompileResult {
333+ self ( input)
334+ }
335+ }
336+
337+ impl < F > From < F > for DynPrecompile
338+ where
339+ F : Fn ( PrecompileInput < ' _ > ) -> PrecompileResult + Send + Sync + ' static ,
320340{
321- fn call ( & self , data : & [ u8 ] , gas : u64 ) -> PrecompileResult {
322- self ( data , gas )
341+ fn from ( f : F ) -> Self {
342+ Self ( Arc :: new ( f ) )
323343 }
324344}
325345
326346impl Precompile for DynPrecompile {
327- fn call ( & self , data : & [ u8 ] , gas : u64 ) -> PrecompileResult {
328- self . 0 . call ( data , gas )
347+ fn call ( & self , input : PrecompileInput < ' _ > ) -> PrecompileResult {
348+ self . 0 . call ( input )
329349 }
330350}
331351
332352impl Precompile for & DynPrecompile {
333- fn call ( & self , data : & [ u8 ] , gas : u64 ) -> PrecompileResult {
334- self . 0 . call ( data , gas )
353+ fn call ( & self , input : PrecompileInput < ' _ > ) -> PrecompileResult {
354+ self . 0 . call ( input )
335355 }
336356}
337357
338358impl < A : Precompile , B : Precompile > Precompile for Either < A , B > {
339- fn call ( & self , data : & [ u8 ] , gas : u64 ) -> PrecompileResult {
359+ fn call ( & self , input : PrecompileInput < ' _ > ) -> PrecompileResult {
340360 match self {
341- Self :: Left ( p) => p. call ( data , gas ) ,
342- Self :: Right ( p) => p. call ( data , gas ) ,
361+ Self :: Left ( p) => p. call ( input ) ,
362+ Self :: Right ( p) => p. call ( input ) ,
343363 }
344364 }
345365}
@@ -371,7 +391,14 @@ mod tests {
371391 _ => panic ! ( "Expected dynamic precompiles" ) ,
372392 } ;
373393
374- let result = dyn_precompile. call ( & test_input, gas_limit) . unwrap ( ) ;
394+ let result = dyn_precompile
395+ . call ( PrecompileInput {
396+ data : & test_input,
397+ gas : gas_limit,
398+ caller : Address :: ZERO ,
399+ value : U256 :: ZERO ,
400+ } )
401+ . unwrap ( ) ;
375402 assert_eq ! ( result. bytes, test_input, "Identity precompile should return the input data" ) ;
376403
377404 // define a function to modify the precompile
@@ -381,7 +408,7 @@ mod tests {
381408 // define a function to modify the precompile to always return a constant value
382409 spec_precompiles. map_precompile ( & identity_address, move |_original_dyn| {
383410 // create a new DynPrecompile that always returns our constant
384- |_data : & [ u8 ] , _gas : u64 | -> PrecompileResult {
411+ |_input : PrecompileInput < ' _ > | -> PrecompileResult {
385412 Ok ( PrecompileOutput { gas_used : 10 , bytes : Bytes :: from_static ( b"constant value" ) } )
386413 }
387414 . into ( )
@@ -395,7 +422,14 @@ mod tests {
395422 _ => panic ! ( "Expected dynamic precompiles" ) ,
396423 } ;
397424
398- let result = dyn_precompile. call ( & test_input, gas_limit) . unwrap ( ) ;
425+ let result = dyn_precompile
426+ . call ( PrecompileInput {
427+ data : & test_input,
428+ gas : gas_limit,
429+ caller : Address :: ZERO ,
430+ value : U256 :: ZERO ,
431+ } )
432+ . unwrap ( ) ;
399433 assert_eq ! (
400434 result. bytes, constant_bytes,
401435 "Modified precompile should return the constant value"
@@ -409,15 +443,22 @@ mod tests {
409443 let gas_limit = 1000 ;
410444
411445 // define a closure that implements the precompile functionality
412- let closure_precompile = |data : & [ u8 ] , _gas : u64 | -> PrecompileResult {
446+ let closure_precompile = |input : PrecompileInput < ' _ > | -> PrecompileResult {
413447 let mut output = b"processed: " . to_vec ( ) ;
414- output. extend_from_slice ( data. as_ref ( ) ) ;
448+ output. extend_from_slice ( input . data . as_ref ( ) ) ;
415449 Ok ( PrecompileOutput { gas_used : 15 , bytes : Bytes :: from ( output) } )
416450 } ;
417451
418452 let dyn_precompile: DynPrecompile = closure_precompile. into ( ) ;
419453
420- let result = dyn_precompile. call ( & test_input, gas_limit) . unwrap ( ) ;
454+ let result = dyn_precompile
455+ . call ( PrecompileInput {
456+ data : & test_input,
457+ gas : gas_limit,
458+ caller : Address :: ZERO ,
459+ value : U256 :: ZERO ,
460+ } )
461+ . unwrap ( ) ;
421462 assert_eq ! ( result. gas_used, 15 ) ;
422463 assert_eq ! ( result. bytes, expected_output) ;
423464 }
@@ -434,7 +475,15 @@ mod tests {
434475 let precompile = spec_precompiles. get ( & identity_address) ;
435476 assert ! ( precompile. is_some( ) , "Identity precompile should exist" ) ;
436477
437- let result = precompile. unwrap ( ) . call ( & test_input, gas_limit) . unwrap ( ) ;
478+ let result = precompile
479+ . unwrap ( )
480+ . call ( PrecompileInput {
481+ data : & test_input,
482+ gas : gas_limit,
483+ caller : Address :: ZERO ,
484+ value : U256 :: ZERO ,
485+ } )
486+ . unwrap ( ) ;
438487 assert_eq ! ( result. bytes, test_input, "Identity precompile should return the input data" ) ;
439488
440489 let nonexistent_address = address ! ( "0x0000000000000000000000000000000000000099" ) ;
@@ -452,7 +501,15 @@ mod tests {
452501 "Identity precompile should exist after conversion to dynamic"
453502 ) ;
454503
455- let result = dyn_precompile. unwrap ( ) . call ( & test_input, gas_limit) . unwrap ( ) ;
504+ let result = dyn_precompile
505+ . unwrap ( )
506+ . call ( PrecompileInput {
507+ data : & test_input,
508+ gas : gas_limit,
509+ caller : Address :: ZERO ,
510+ value : U256 :: ZERO ,
511+ } )
512+ . unwrap ( ) ;
456513 assert_eq ! (
457514 result. bytes, test_input,
458515 "Identity precompile should return the input data after conversion to dynamic"
0 commit comments