EVM Precompiles
Precompiles are special contracts accessible at fixed addresses that execute native runtime logic instead of EVM bytecode. They allow EVM clients — including MetaMask and other Ethereum wallets — to interact directly with Substrate pallets and cryptographic primitives without needing a custom JSON-RPC endpoint.
Orbinum exposes three groups of precompiles: Ethereum standard precompiles, Frontier non-standard precompiles, and Orbinum-specific precompiles.
Address Convention
Precompile addresses follow the Frontier convention:
H160::from_low_u64_be(n)
where n is a small integer. This produces an address of the form
0x0000000000000000000000000000000000000NNN.
Ethereum Standard Precompiles
These are the precompiles defined in the Ethereum Yellow Paper and its EIPs. They are available at the same addresses as Ethereum mainnet.
| Address | Name | Description |
|---|---|---|
0x0000000000000000000000000000000000000001 | ECRecover | ECDSA signature recovery |
0x0000000000000000000000000000000000000002 | SHA-256 | SHA-2 256-bit hash |
0x0000000000000000000000000000000000000003 | RIPEMD-160 | RIPEMD 160-bit hash |
0x0000000000000000000000000000000000000004 | Identity | Data copy (identity function) |
0x0000000000000000000000000000000000000005 | Modexp | Modular exponentiation (EIP-198) |
Frontier Non-Standard Precompiles
These precompiles are provided by Frontier for Substrate-based chains. They are not part of the Ethereum standard and are only available on Frontier-compatible networks.
| Address | Name | Description |
|---|---|---|
0x0000000000000000000000000000000000000400 | SHA3-FIPS-256 | FIPS 202-compliant Keccak-256 |
0x0000000000000000000000000000000000000401 | ECRecoverPublicKey | ECDSA public key recovery |
0x0000000000000000000000000000000000000402 | Curve25519Add | Curve25519 point addition |
0x0000000000000000000000000000000000000403 | Curve25519ScalarMul | Curve25519 scalar multiplication |
Orbinum Precompiles
These precompiles expose Orbinum-specific runtime pallets to EVM clients. They are deployed in the
0x0800–0x08FF range to avoid collisions with standard and Frontier precompiles.
| Address | Name | Description |
|---|---|---|
0x0000000000000000000000000000000000000800 | AccountMapping | Link EVM and Substrate accounts |
0x0000000000000000000000000000000000000801 | ShieldedPool | Shield, transfer, and unshield tokens using ZK proofs |
Address Derivation
Orbinum precompile indices map as follows:
| Index | Hex Address |
|---|---|
2048 (0x800) | 0x…0000000000000000000000000000000000000800 |
2049 (0x801) | 0x…0000000000000000000000000000000000000801 |
Calling a Precompile
From Solidity:
interface IShieldedPool {
function shield(
uint32 assetId,
uint256 amount,
bytes32 commitment,
bytes calldata encryptedMemo
) external;
}
IShieldedPool pool = IShieldedPool(0x0000000000000000000000000000000000000801);
pool.shield(0, 1e18, commitment, memo);
From ethers.js:
import { ethers } from "ethers";
const abi = ["function shield(uint32,uint256,bytes32,bytes)"];
const precompile = new ethers.Contract(
"0x0000000000000000000000000000000000000801",
abi,
signer
);
await precompile.shield(0, ethers.parseEther("1"), commitment, memo);
Security Notes
- Orbinum precompiles use
AddressMappingto derive the caller'sAccountId32from the EVMH160sender. No signature verification is repeated inside the precompile — the EVM transaction already provides authentication. - Precompiles do not return values beyond a success indicator. Use RPC or events to confirm state changes.
- Gas costs are estimated conservatively. They may be adjusted before mainnet.