If you're building payment infrastructure on Ethereum L2s, RIP-7212 is the most important precompile you've never heard of.
The Problem
EMV payment cards (Visa, Mastercard, and now OpenPasskey) use P-256 (secp256r1) elliptic curve cryptography. Ethereum natively supports secp256k1 (a different curve). Verifying a P-256 signature in Solidity costs approximately 300,000 gas, making on-chain card payment verification economically impractical.
The Solution: RIP-7212
RIP-7212 adds a precompiled contract for P-256 signature verification at address 0x100. It reduces verification cost from ~300K gas to ~3,450 gas.
This is deployed on:
- Base (Coinbase's L2)
- Optimism
- Polygon
- Arbitrum
- And several other L2s
Why It Matters for Payments
With RIP-7212, you can:
- Verify EMV card signatures on-chain at minimal cost
- Build trustless payment settlement without centralized processors
- Enable card-to-blockchain bridges that don't require trusted intermediaries
How We Use It at OpenPasskey
Our payment flow:
Card Tap → P-256 Signature → Base L2 → RIP-7212 Verify → ClearingVault → Merchant
- Customer taps their OpenPasskey card (Java Card with P-256 key pair)
- Card signs transaction data (amount, merchant, nonce)
- Signature submitted to Base L2
- Smart contract calls RIP-7212 precompile to verify (~3,450 gas, sub-cent)
- ClearingVault releases AUD stablecoins to merchant's CREATE2 receiver
- Merchant gets AUD in their bank account
Total on-chain cost: fractions of a cent.
Settlement time: seconds.
Intermediary fees: zero.
The Broader Implication
There are 11+ billion EMV cards in circulation globally. All modern ones use P-256 or compatible curves. RIP-7212 means any of these cards could theoretically interact with on-chain settlement.
We're proving this with physical cards in 20+ Sydney cafes. 3,200+ users. 45,509 transactions.
For Developers
If you're building on Base or any L2 with RIP-7212:
// Verify P-256 signature via precompile
function verifyP256(
bytes32 messageHash,
bytes32 r,
bytes32 s,
bytes32 x,
bytes32 y
) internal view returns (bool) {
(bool success, bytes memory result) = address(0x100).staticcall(
abi.encode(messageHash, r, s, x, y)
);
return success && abi.decode(result, (uint256)) == 1;
}
This opens up payment applications that were previously impossible on-chain.
Top comments (0)