@@ -835,6 +835,46 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
835835 }
836836 }
837837
838+ /// Execute a system-level call as defined by EIP-4788, EIP-2935, EIP-7002, EIP-7251,
839+ /// and future EIPs.
840+ ///
841+ /// System calls are made by the protocol itself at the start of each block, before any user
842+ /// transactions are processed. They follow the call semantics of a regular `CALL` with these
843+ /// specific properties:
844+ /// - `caller` is the protocol-defined `SYSTEM_ADDRESS` (`0xfffffffffffffffffffffffffffffffffffffffe`).
845+ /// - `value` is always zero — no ETH is transferred.
846+ /// - `address` — the system contract to call (e.g. the `beacon_root` or `blockhash` contract).
847+ /// - `data` — ABI-encoded call data passed to the system contract.
848+ /// - **Gas limit** is implicitly inherited from the executor's `metadata`. According to EIPs,
849+ /// the host must initialize the executor with exactly `30_000_000` gas prior to this call.
850+ ///
851+ /// Additional behavioral overrides:
852+ /// - No `Transfer` is performed: balance checks on the caller are skipped entirely.
853+ /// - The caller's nonce is not incremented, and no base transaction cost is recorded.
854+ /// - The call is not static, meaning the callee can freely modify the state.
855+ pub fn system_call (
856+ & mut self ,
857+ caller : H160 ,
858+ address : H160 ,
859+ data : Vec < u8 > ,
860+ ) -> ( ExitReason , Vec < u8 > ) {
861+ let context = Context {
862+ caller,
863+ address,
864+ apparent_value : U256 :: zero ( ) ,
865+ } ;
866+
867+ match self . call_inner ( address, None , data, None , false , false , false , context) {
868+ Capture :: Exit ( ( s, v) ) => emit_exit ! ( s, v) ,
869+ Capture :: Trap ( rt) => {
870+ let mut cs: SmallVec < [ TaggedRuntime < ' _ > ; DEFAULT_CALL_STACK_CAPACITY ] > =
871+ smallvec ! ( rt. 0 ) ;
872+ let ( s, _, v) = self . execute_with_call_stack ( & mut cs) ;
873+ emit_exit ! ( s, v)
874+ }
875+ }
876+ }
877+
838878 /// Get used gas for the current executor, given the price.
839879 pub fn used_gas ( & self ) -> u64 {
840880 // Avoid uncontrolled `u64` casting
0 commit comments