foundry_evm_core/
precompiles.rs

1use alloy_primitives::{address, Address, Bytes, B256};
2use revm::{
3    precompile::{secp256r1::p256_verify as revm_p256_verify, PrecompileWithAddress},
4    primitives::{Precompile, PrecompileResult},
5};
6
7/// The ECRecover precompile address.
8pub const EC_RECOVER: Address = address!("0000000000000000000000000000000000000001");
9
10/// The SHA-256 precompile address.
11pub const SHA_256: Address = address!("0000000000000000000000000000000000000002");
12
13/// The RIPEMD-160 precompile address.
14pub const RIPEMD_160: Address = address!("0000000000000000000000000000000000000003");
15
16/// The Identity precompile address.
17pub const IDENTITY: Address = address!("0000000000000000000000000000000000000004");
18
19/// The ModExp precompile address.
20pub const MOD_EXP: Address = address!("0000000000000000000000000000000000000005");
21
22/// The ECAdd precompile address.
23pub const EC_ADD: Address = address!("0000000000000000000000000000000000000006");
24
25/// The ECMul precompile address.
26pub const EC_MUL: Address = address!("0000000000000000000000000000000000000007");
27
28/// The ECPairing precompile address.
29pub const EC_PAIRING: Address = address!("0000000000000000000000000000000000000008");
30
31/// The Blake2F precompile address.
32pub const BLAKE_2F: Address = address!("0000000000000000000000000000000000000009");
33
34/// The PointEvaluation precompile address.
35pub const POINT_EVALUATION: Address = address!("000000000000000000000000000000000000000a");
36
37/// Precompile addresses.
38pub const PRECOMPILES: &[Address] = &[
39    EC_RECOVER,
40    SHA_256,
41    RIPEMD_160,
42    IDENTITY,
43    MOD_EXP,
44    EC_ADD,
45    EC_MUL,
46    EC_PAIRING,
47    BLAKE_2F,
48    POINT_EVALUATION,
49    ODYSSEY_P256_ADDRESS,
50];
51
52/// [EIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md) secp256r1 precompile address on Odyssey.
53///
54/// <https://github.com/ithacaxyz/odyssey/blob/482f4547631ae5c64ebea6a4b4ef93184a4abfee/crates/node/src/evm.rs#L35-L35>
55pub const ODYSSEY_P256_ADDRESS: Address = address!("0000000000000000000000000000000000000014");
56
57/// Wrapper around revm P256 precompile, matching EIP-7212 spec.
58///
59/// Per Optimism implementation, P256 precompile returns empty bytes on failure, but per EIP-7212 it
60/// should be 32 bytes of zeros instead.
61pub fn p256_verify(input: &Bytes, gas_limit: u64) -> PrecompileResult {
62    revm_p256_verify(input, gas_limit).map(|mut result| {
63        if result.bytes.is_empty() {
64            result.bytes = B256::default().into();
65        }
66
67        result
68    })
69}
70
71/// [EIP-7212](https://eips.ethereum.org/EIPS/eip-7212#specification) secp256r1 precompile.
72pub const ODYSSEY_P256: PrecompileWithAddress =
73    PrecompileWithAddress(ODYSSEY_P256_ADDRESS, Precompile::Standard(p256_verify));