ECREC
Signature verification
Recover the address that produced an ECDSA signature over a 32-byte hash.
| Address | 0x0000000000000000000000000000000000000001 |
|---|---|
| Name | ECREC |
| Minimum gas | 3,000 |
| Input | 128 bytes |
| Output | 32 bytes, or empty on failure |
| Available since | Frontier |
Input
hash32 B
v32 B
r32 B
s32 B
| Offset | Length | Field | Description |
|---|---|---|---|
| 0 | 32 | hash | The 32-byte message hash that was signed. |
| 32 | 32 | v | Recovery identifier, 27 or 28, big-endian in the low byte. Bytes 32–62 must be zero. |
| 64 | 32 | r | First 32 bytes of the signature. |
| 96 | 32 | s | Second 32 bytes of the signature. |
Output
The recovered 20-byte address, left-padded to a 32-byte word.
Gas
3000
Failure behaviour
- Returns empty data with no error if
vis not 27 or 28, if bytes 32–62 are non-zero, if the signature is malformed, or if recovery fails. - Gas is consumed in full either way.
- Input shorter than the expected length is right-padded with zero bytes rather than rejected.
Notes
- Returning empty rather than a zero word is the classic footgun: a caller that only checks the returned data length, or that reads a stale memory slot, can read failure as success. Always check the returned data size, and never compare the result against an attacker-supplied address without that check.
- Frost still ships this precompile for Ethereum compatibility, but the chain itself no longer depends on secp256k1 anywhere in its deployment or treasury flow.
Calling it
Precompiles have no ABI and no function selector: the input is raw bytes at the exact offsets above. Call with staticcall.
// ECREC at 0x01(bool ok, bytes memory out) = address(0x01).staticcall(input);require(ok, "ECREC reverted");