From 3fc3fddb3f7e26cc299514ceab3ddfd006b70fb9 Mon Sep 17 00:00:00 2001 From: theochap Date: Tue, 28 Oct 2025 23:13:21 -0400 Subject: [PATCH] feat(precompiles/jovian): add jovian precompiles to alloy-evm --- Cargo.toml | 2 +- crates/op-evm/src/lib.rs | 166 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8fd4e5da..0cc4ec38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ op-alloy-rpc-types-engine = { version = "0.21", default-features = false } # revm revm = { version = "30.0.0", default-features = false } -op-revm = { version = "11.2.0", default-features = false } +op-revm = { version = "11.3.0", default-features = false } # misc auto_impl = "1" diff --git a/crates/op-evm/src/lib.rs b/crates/op-evm/src/lib.rs index 0388c0a2..3d8f3804 100644 --- a/crates/op-evm/src/lib.rs +++ b/crates/op-evm/src/lib.rs @@ -210,3 +210,169 @@ impl EvmFactory for OpEvmFactory { } } } + +#[cfg(test)] +mod tests { + use alloc::{string::ToString, vec}; + use alloy_evm::{ + precompiles::{Precompile, PrecompileInput}, + EvmInternals, + }; + use alloy_primitives::U256; + use op_revm::precompiles::{bls12_381, bn254_pair}; + use revm::{ + context::{CfgEnv, JournalTr}, + database::EmptyDB, + precompile::PrecompileError, + Journal, JournalEntry, + }; + + use super::*; + + #[test] + fn test_precompiles_jovian_fail() { + let evm = OpEvmFactory::default().create_evm( + EmptyDB::default(), + EvmEnv::new(CfgEnv::new_with_spec(OpSpecId::JOVIAN), BlockEnv::default()), + ); + + let jovian_precompile = evm.precompiles().get(bn254_pair::JOVIAN.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bn254_pair::JOVIAN_MAX_INPUT_SIZE + 1], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_err()); + assert!(matches!(result.unwrap_err(), PrecompileError::Bn254PairLength)); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_G1_MSM.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_G1_MSM_MAX_INPUT_SIZE + 1], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_err()); + assert!(result.unwrap_err().to_string().contains("G1MSM input length too long")); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_G2_MSM.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_G2_MSM_MAX_INPUT_SIZE + 1], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_err()); + assert!(result.unwrap_err().to_string().contains("G2MSM input length too long")); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_PAIRING.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_PAIRING_MAX_INPUT_SIZE + 1], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_err()); + assert!(result.unwrap_err().to_string().contains("Pairing input length too long")); + } + + #[test] + fn test_precompiles_jovian() { + let evm = OpEvmFactory::default().create_evm( + EmptyDB::default(), + EvmEnv::new(CfgEnv::new_with_spec(OpSpecId::JOVIAN), BlockEnv::default()), + ); + let jovian_precompile = evm.precompiles().get(bn254_pair::JOVIAN.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bn254_pair::JOVIAN_MAX_INPUT_SIZE], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_ok()); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_G1_MSM.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_G1_MSM_MAX_INPUT_SIZE], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_ok()); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_G2_MSM.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_G2_MSM_MAX_INPUT_SIZE], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_ok()); + + let jovian_precompile = evm.precompiles().get(bls12_381::JOVIAN_PAIRING.address()).unwrap(); + let result = jovian_precompile.call(PrecompileInput { + data: &vec![0; bls12_381::JOVIAN_PAIRING_MAX_INPUT_SIZE], + gas: u64::MAX, + caller: Address::ZERO, + value: U256::ZERO, + target_address: Address::ZERO, + bytecode_address: Address::ZERO, + internals: EvmInternals::new( + &mut Journal::::new(EmptyDB::default()), + &BlockEnv::default(), + ), + }); + + assert!(result.is_ok()); + } +}