Precompile ABI

Addresses, input layout, gas and return value, in one table.

Docs / Reference / Precompile ABI

One table, for looking up. The explanations are on The five precompiles and Falcon input framing.

Mainnet

AddressFunctionStandardGasInputOutput
0x0AE1Falcon-512 verifyNIST Falcon round 340,000`pk(897) \\sm`32-byte word, …01 valid
0x0AE2Falcon-1024 verifyNIST Falcon round 375,000`pk(1793) \\sm`32-byte word, …01 valid
0x0AE3ML-DSA-44 verifyFIPS 20455,000`pk(1312) \\sig(2420) \\message`32-byte word, …01 valid
0x0AE4SLH-DSA-SHA2-128s verifyFIPS 205350,000`pk(32) \\sig(7856) \\message`32-byte word, …01 valid
0x0AE5SHAKE256 XOFFIPS 20260 + 12 per 32-byte word of input plus output32-byte big-endian outLen, then dataoutLen bytes

Active from block 9,189,161. Gas is flat for the four verifiers.

Falcon sm layout

sm   = sigLen(2, big-endian) || nonce(40) || message || esig
esig = (0x20 + logn) || compressedSignature
       0x29 for Falcon-512, 0x2A for Falcon-1024
sigLen == len(esig)
pk   = (0x00 + logn) || packed_h
       0x09 for Falcon-512, 0x0A for Falcon-1024

The message is in the middle. Signature length is variable and must be read per call.

ML-DSA and SLH-DSA layout

sm = signature || message, with the fixed signature lengths above. Everything after pk || sig is the message.

SHAKE256 behaviour

Output length above 65,536 is capped to 65,536. A non-zero high 28 bytes of the length word also caps. Input shorter than 32 bytes returns empty output.

Failure behaviour

The verifiers never revert. Malformed input returns the 32-byte zero word, exactly as an invalid signature does. Put a known-good vector in the same run as a positive control, or a zero tells you nothing.

Testnet only

0x0AE6 (ML-KEM-768 deterministic encapsulation, FIPS 203) and 0x0AE7 exist on the public testnet and are not on mainnet.

Test vectors

The NIST Known-Answer Test vectors used against these implementations ship in the node package under vectors/.