Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
Free 30-min Web3 Consultation
Book Now
Smart Contract Security Audits
Learn More
Custom DeFi Protocol Development
Explore
Full-Stack Web3 dApp Development
View Services
LABS
Guides

How to Manage EVM Precompile Usage

A technical guide for developers on identifying, interacting with, and optimizing the use of EVM precompiled contracts for cryptographic operations and gas efficiency.
Chainscore © 2026
introduction
DEVELOPER GUIDE

How to Manage EVM Precompile Usage

A practical guide for developers on how to identify, call, and optimize the use of EVM precompiled contracts in smart contracts.

Ethereum Virtual Machine (EVM) precompiles are a set of native, gas-efficient contracts at fixed addresses (0x01 to 0x09 and beyond) that perform complex cryptographic and computational operations. Unlike standard smart contracts, their logic is implemented directly in the EVM client (e.g., Geth, Erigon), making them significantly cheaper to execute. Common precompiles handle operations like elliptic curve pairing for zk-SNARKs (ecrecover at 0x01), SHA-256 hashing (0x02), and modular exponentiation for RSA verification (0x05). Managing their usage effectively is key to writing optimized, cost-effective smart contracts.

To call a precompile, you interact with its address using a low-level call or staticcall. The operation's input data must be formatted according to its specific specification. For example, to recover the signer's address from a signature using ecrecover (0x01), you must pack the hash and v, r, s signature components correctly. Failing to provide the exact byte sequence defined in the Ethereum Yellow Paper will result in a failed call. Always verify the precompile's expected input and output formats from the official documentation before integration.

Effective management involves auditing gas costs and security. While precompiles are cheap, their cost scales with input size and complexity. For instance, the bn256Pairing precompile (0x08) used in zk-rollups has a high base gas cost that increases per pairing. Use tools like Hardhat or Foundry's gas reporters to profile calls. Security is paramount: never trust unverified return data. A precompile call returns a success boolean and bytes memory data; you must check success and decode the output correctly. Malformed inputs can lead to silent failures or wasted gas.

Optimization strategies include batching operations and using precompiles over custom Solidity. For repetitive hashing with SHA256 or RIPEMD-160, a single call to precompiles 0x02 or 0x03 is far cheaper than Solidity implementations. In advanced use cases like integrating cryptographic primitives for Layer 2 scaling, understanding the specific precompiles for BN254 elliptic curve operations (0x07, 0x08) is essential. Developers should reference chain-specific documentation, as precompile sets and gas pricing can differ on networks like Polygon, Arbitrum, or Avalanche's C-Chain.

prerequisites
PREREQUISITES

How to Manage EVM Precompile Usage

A guide to understanding and interacting with EVM precompiled contracts, which provide optimized, low-level access to cryptographic and state operations on the blockchain.

EVM precompiles are a set of specialized smart contracts with hardcoded addresses, typically from 0x01 to 0x09 on Ethereum Mainnet. Unlike standard contracts, their logic is implemented directly in the EVM client (e.g., Geth, Nethermind) at the protocol level, making them extremely gas-efficient for specific computations. Common uses include cryptographic operations like ecrecover for signature verification, SHA256 and RIPEMD-160 hashing, and the alt_bn128 curve operations essential for zk-SNARKs and rollups. Understanding their addresses and gas costs is fundamental for developers building performant dApps.

To use a precompile, you call its fixed address as if it were a regular contract. The input data format is strictly defined and must be packed correctly. For example, the ecrecover precompile at 0x01 expects a 128-byte input: a 32-byte message hash followed by the v, r, and s signature parameters. A failed call, such as providing malformed input, will consume all provided gas and return empty data. It's critical to consult the official Ethereum Yellow Paper or client documentation for exact specifications, as behavior can differ slightly between EVM-compatible chains like Polygon or Arbitrum.

Managing precompile usage effectively requires knowing the gas cost schedule. Operations like ecadd (elliptic curve addition) are cheap, while ecpairing for zk-SNARK verification is more expensive but still far cheaper than a Solidity implementation. Always pre-calculate gas in tests. Furthermore, some L2s and alternative EVM chains disable or modify certain precompiles. For instance, a chain might disable the deprecated 0x05 (modexp) or adjust gas costs. Always verify the active precompiles on your target network by checking the chain's documentation or using a simple call to the precompile address to test for functionality.

When writing smart contracts that use precompiles, you typically interact with them via inline assembly or low-level call. In Solidity, a call to the SHA256 precompile looks like: (bool success, bytes memory result) = address(0x02).call(inputData);. You must handle the success flag and decode the result bytes. For frequent use, consider wrapping precompile calls in a library for better code reuse and safety. Thorough testing is non-negotiable—simulate calls in a forked mainnet environment or a local testnet to ensure correct input encoding and gas estimation.

Beyond the standard set, some networks introduce custom precompiles to expose native chain functionality. For example, the 0x42 address on the C-Chain might handle Avalanche's native cross-chain transfers. To manage these, you must rely on the specific chain's developer docs. As a best practice, audit and limit precompile calls in your contracts, as they are powerful but low-level. An error can lead to total gas loss. By mastering precompile addresses, input formats, gas costs, and chain-specific behaviors, you can build highly optimized and interoperable blockchain applications.

key-precompiles
DEVELOPER GUIDE

Core EVM Precompiles

EVM precompiles are gas-optimized, built-in smart contracts for essential cryptographic and state operations. This guide covers their usage, costs, and security considerations.

01

What Are EVM Precompiles?

Precompiles are hardcoded contracts at specific addresses (e.g., 0x01 to 0x09) that perform complex computations more efficiently than Solidity. They are written in the EVM's native language and cost significantly less gas. Common uses include:

  • Elliptic curve operations (e.g., ecrecover at 0x01)
  • Hash functions (SHA256, RIPEMD-160)
  • Big integer modular exponentiation (modexp at 0x05) Using them directly via staticcall is a key optimization for protocols like rollups and bridges.
02

Gas Costs and Optimization

Each precompile has a deterministic gas cost formula. For example, the ecadd (elliptic curve addition) precompile at 0x06 costs 500 gas, while a modexp operation's cost scales with input size. Optimizing precompile calls involves:

  • Batching operations to reduce call overhead.
  • Validating inputs off-chain where possible to avoid failed, paid executions.
  • Using staticcall for pure functions to enforce state non-modification. Misestimating gas can lead to out-of-gas reverts in complex computations like pairing checks for zk-SNARKs.
03

Security Best Practices

While precompiles are considered secure, their integration requires caution. Key practices include:

  • Input Validation: Always check precompile inputs for length and format to prevent unexpected reverts or, in rare cases, incorrect results from edge cases.
  • Reentrancy Guards: Although most precompiles are stateless, wrap calls in non-reentrant functions if they are part of a larger state-changing operation.
  • Address Aliasing: Be aware that some L2s (like Arbitrum) may alias precompile addresses; always use the canonical ADDRESS constant from the chain's documentation.
04

Common Precompile Addresses & Uses

Here are the most frequently used precompiles:

  • 0x01 (ecrecover): Recovers the signer address from an ECDSA signature.
  • 0x02 (sha256): Computes SHA256 hash.
  • 0x03 (ripemd160): Computes RIPEMD-160 hash.
  • 0x05 (modexp): Performs modular exponentiation for RSA verification.
  • 0x06 & 0x07: Perform elliptic curve addition and scalar multiplication on the alt_bn128 curve, crucial for zk-SNARK verification.
  • 0x08 (ecpairing): Performs a pairing check on the alt_bn128 curve, used by rollups like zkSync.
05

Testing Precompile Interactions

Test precompile calls thoroughly using forked mainnet environments in Hardhat or Foundry. Key steps:

  1. Use a Mainnet Fork: Precompiles exist at the protocol level; local EVMs (like Hardhat Network) may not implement all of them correctly.
  2. Gas Snapshotting: Use Foundry's --gas-report or Hardhat's gas reporter to verify optimization claims.
  3. Edge Case Tests: Provide invalid inputs (e.g., malformed signatures for ecrecover) to ensure your contract handles reverts gracefully. Failing precompile calls still consume all provided gas up to the limit.
EIP-2535: DIAMOND STANDARD

Precompile Addresses and Functions

Core Ethereum precompiles with their fixed addresses, gas costs, and primary use cases.

Precompile NameAddressGas Cost (approx.)Function

ecrecover

0x01

3000

Verify ECDSA signature and recover public key

SHA256

0x02

60 + 12 per word

Compute SHA-256 hash

RIPEMD160

0x03

600 + 120 per word

Compute RIPEMD-160 hash

Identity

0x04

15 + 3 per word

Return input data (copy)

Modular Exponentiation

0x05

Dynamic

Compute (base^exp) % mod for RSA/zk-SNARKs

BN256Add

0x06

500

Elliptic curve point addition on alt_bn128

BN256ScalarMul

0x07

40000

Elliptic curve scalar multiplication on alt_bn128

BN256Pairing

0x08

100000 + 80000 per pair

Bilinear pairing on alt_bn128 for zk-SNARKs

how-to-call-precompiles
GUIDE

How to Call a Precompile in Solidity

EVM precompiles are gas-efficient, native contracts for cryptographic operations. This guide explains how to call them directly in your Solidity code.

An Ethereum precompile is a special contract address with native, optimized bytecode embedded directly in the EVM client. Unlike standard smart contracts, precompiles execute complex operations—like cryptographic hashing or elliptic curve operations—with minimal gas cost and maximum efficiency. They are accessible at fixed, reserved addresses below 0x000000000000000000000000000000000000ffff. Common examples include ecrecover at 0x01 for signature verification, and the SHA256 hash function at 0x02. Calling them is a fundamental skill for building performant DeFi, identity, and scaling solutions.

To call a precompile, you use a low-level staticcall or call to its address. Since precompiles have no stored bytecode, you must provide the correct input data bytes payload that matches the function's expected interface. The operation is performed using inline assembly (assembly { ... }) or the address.call() pattern. For instance, performing a ripemd160 hash requires you to send the pre-decomputed input data to address 0x03. The call will return success and the resulting bytes output, which you must then decode.

Here is a concrete example of calling the ecrecover precompile to verify an ECDSA signature. The function takes the digest hash and the v, r, s signature components, packs them into memory, and executes the call.

solidity
function recoverSigner(bytes32 hash, uint8 v, bytes32 r, bytes32 s) public pure returns (address) {
    bytes memory data = abi.encodePacked(hash, v, r, s);
    (bool success, bytes memory result) = address(0x01).staticcall(data);
    require(success, "Precompile call failed");
    return abi.decode(result, (address));
}

This pattern—encode input, low-level call, decode output—is consistent across most precompiles.

Key considerations for precompile usage include gas cost predictability and input validation. While cheaper than implementing operations in Solidity, gas costs are not zero; they are defined in the Ethereum Yellow Paper. Always validate the success flag and returned data length. Furthermore, some precompiles, like those for BN256 pairing checks (addresses 0x08 and 0x09) used by zk-SNARKs, have complex ABI encodings. Refer to the official Ethereum Precompiles documentation for exact input/output formats.

Advanced use cases involve precompiles specific to other EVM-compatible chains. For example, Arbitrum uses precompiles for retryable ticket creation, and Polygon zkEVM has precompiles for bridge operations. Always check the chain's documentation. When writing portable code, consider wrapping precompile calls in a library or abstract contract to handle chain-specific address and interface differences, ensuring your protocol remains flexible across multiple Layer 2 and sidechain environments.

PRACTICAL IMPLEMENTATION

Code Examples for Common Precompiles

Core Cryptographic Precompiles

Ethereum's most frequently used precompiles provide gas-efficient cryptographic operations. The ecrecover function at address 0x01 is essential for signature verification, consuming a fixed 3,000 gas. The sha256 (0x02) and ripemd160 (0x03) hash functions are used for data integrity checks and Bitcoin-compatible address generation, costing 60 + 12 gas per word and 600 + 120 gas per word respectively.

solidity
// Example: Verifying an ECDSA signature with ecrecover
function verifySignature(
    bytes32 messageHash,
    uint8 v,
    bytes32 r,
    bytes32 s,
    address expectedSigner
) public pure returns (bool) {
    address recovered = ecrecover(messageHash, v, r, s);
    return recovered == expectedSigner;
}

For elliptic curve operations, the bn256 precompiles (0x06, 0x07, 0x08) enable zk-SNARK verification and pairing checks, crucial for rollups like Aztec and privacy applications.

chain-specific-precompiles
GUIDE

Chain-Specific Precompiles

Learn how to identify, interact with, and manage the unique precompiled contracts available on different EVM-compatible chains.

Ethereum Virtual Machine (EVM) precompiles are special contracts with hardcoded addresses (from 0x01 to 0x09 on Ethereum mainnet) that provide optimized, gas-efficient implementations of complex cryptographic operations like ecrecover, SHA-256 hashing, and elliptic curve pairings. However, many Layer 1 and Layer 2 chains extend this set with their own chain-specific precompiles to enable native functionality, such as random number generation, custom signature schemes, or gas-efficient storage proofs. Understanding these extensions is crucial for developers building portable, gas-optimized applications.

To manage precompile usage, you must first identify which ones are available on your target chain. Consult the chain's official documentation, such as the Avalanche Docs for its Native Minting precompile or Polygon zkEVM Docs for its bridge precompiles. You can also inspect the chain's hardfork configuration or use a block explorer to check if calls to known precompile addresses (e.g., 0xfe for the BLS12-381 pairing on Ethereum) succeed. Writing chain-agnostic code requires feature detection, often by checking chainId and using try/catch blocks when calling a precompile address.

Interacting with a precompile is done via a low-level call or staticcall. The interface is defined by the precompile's expected input encoding and output format. For example, to use the bls12G1Add precompile on Gnosis Chain (address 0x0b), you must pass two compressed G1 points as a 128-byte bytes argument. Always verify the call's success and decode the returned data correctly. Here's a Solidity snippet for a generic precompile call:

solidity
(bool success, bytes memory result) = address(0x0b).staticcall(inputData);
require(success, "Precompile call failed");

Managing gas costs is a primary reason to use precompiles. A native Solidity implementation of the BN256 pairing check might cost over 500k gas, while the 0x08 precompile on Ethereum consumes ~40k gas. However, gas costs for the same operation can vary significantly between chains. Always benchmark your precompile calls on the target network. Furthermore, be aware of activation blocks; a precompile may only be available after a specific hardfork. Your contracts should handle its absence gracefully to avoid deployment failures or runtime errors on unsupported chains.

Security considerations are paramount. Chain-specific precompiles are often less audited than Ethereum's core set. Thoroughly review the precompile's specification for potential edge cases in input validation or output handling. Since precompiles execute outside the standard EVM, they can have unique side-effects or state changes. Treat them as external, trust-minimized components and validate their results within your application logic when possible. For critical operations, consider maintaining a fallback Solidity implementation for chains where the precompile is unavailable.

To effectively manage precompile usage across a multi-chain project, create an abstraction layer. This can be a Solidity library or a set of helper functions that encapsulate the chain detection, interface encoding, and error handling. This pattern keeps your business logic clean and makes it easier to add support for new chains or precompiles in the future. Always document the supported precompiles and their corresponding chain IDs within your codebase to aid other developers and auditors.

tools-and-libraries
EVM PRECOMPILES

Tools and Helper Libraries

Precompiled contracts are gas-efficient, native functions on the EVM. These tools help developers identify, analyze, and integrate them into their smart contracts.

gas-optimization
GUIDE

EVM Precompiles: Gas Optimization and Best Practices

EVM precompiles are optimized, low-level contracts that provide critical cryptographic and utility functions at a fraction of the gas cost of a Solidity implementation. This guide explains how to identify, use, and manage them for maximum efficiency.

Ethereum Virtual Machine (EVM) precompiles are a set of nine (as of the Berlin hardfork) native contracts deployed at fixed addresses, from 0x01 to 0x09. They are written in the EVM's native language and are executed directly by client nodes, bypassing the overhead of the standard EVM interpreter. This makes them orders of magnitude cheaper in terms of gas consumption than performing the same operations in a standard smart contract. Common precompiles handle essential cryptographic primitives like the elliptic curve pairing (0x08) for zk-SNARK verification, SHA256 hashing (0x02), and RIPEMD-160 hashing (0x03).

Using a precompile is straightforward: you call it like any other contract using a low-level call or staticcall. The key is knowing the correct address, input format, and expected output. For example, to compute a SHA256 hash in Solidity, you would use:

solidity
function getSha256(bytes memory data) public view returns (bytes32 result) {
    assembly {
        let success := staticcall(gas(), 0x02, add(data, 0x20), mload(data), add(result, 0x20), 0x20)
        if iszero(success) { revert(0, 0) }
    }
}

This is significantly cheaper than importing and using a Solidity library for SHA256. Always prefer the precompile for these standardized operations.

The primary gas optimization benefit comes from the drastically reduced computational cost. A complex operation like an ECRECOVER (signature verification at 0x01) costs ~3,000 gas, while a Solidity implementation could cost over 100,000 gas. For batch operations or functions called frequently, this difference is critical. However, precompiles have fixed, unchangeable logic. You must ensure your input data is correctly formatted, as malformed data will cause the call to fail and consume all provided gas. Always validate inputs before the call and handle potential failures gracefully in your surrounding contract logic.

Best practices for managing precompile usage include gas benchmarking and fallback mechanisms. Before deployment, benchmark the gas cost of your precompile call against a potential pure-Solidity fallback for your specific use case and data size. While precompiles are almost always cheaper, extremely small data inputs might have different economics. Furthermore, consider the future: while precompile addresses and functions are stable, new hardforks (like Berlin introducing 0x0a for BLAKE2) can add or modify them. Your contract's architecture should not become brittle by hardcoding assumptions about gas costs or output formats that could theoretically change.

Advanced use involves precompiles for zero-knowledge proofs and Layer 2 integration. The BN256 pairing precompile (0x08) is essential for verifying zk-SNARKs and zk-STARKs on-chain, forming the bedrock of many privacy and scaling solutions. Similarly, MODEXP (0x05) is used in RSA verification, which is relevant for certain oracle designs. When building for these advanced use cases, thorough testing on a testnet is non-negotiable. Incorrect use of these mathematical precompiles can lead to silent errors or significant financial loss. Refer to the official Ethereum Improvement Proposals (EIPs)—specifically EIP-198 for MODEXP, EIP-196 for BN256, and EIP-197 for BN256 pairing—for the canonical specifications and test vectors.

EVM PRECOMPILES

Frequently Asked Questions

Common developer questions and troubleshooting for EVM precompiled contracts, covering usage, gas costs, security, and debugging.

EVM precompiles are a set of hardcoded contracts at specific addresses (from 0x01 to 0x09 and beyond) that implement complex cryptographic and utility functions directly in the EVM client's native code, rather than as EVM bytecode. When a call is made to a precompile address, the EVM executes the corresponding native implementation, which is significantly more gas-efficient and faster than running equivalent Solidity code.

Common precompiles include:

  • ecrecover (0x01): Recovers the signer address from an elliptic curve signature.
  • sha256 (0x02): Computes the SHA-256 hash.
  • ripemd160 (0x03): Computes the RIPEMD-160 hash.
  • identity (0x04): Returns the input data (cheap data copy).
  • modExp (0x05): Performs modular exponentiation (used by zk-SNARKs).
  • bn256Add, bn256Mul, bn256Pairing (0x06, 0x07, 0x08): Elliptic curve operations for pairing-based cryptography.

They are invoked using a standard CALL or STATICCALL opcode, and their gas cost is defined in the Ethereum Yellow Paper or network-specific hard forks.

How to Manage EVM Precompile Usage: A Developer Guide | ChainScore Guides