Precompile Summary

AddressNameGasInputOutputIntroducedBehavior
0x10BLS12_MAP_FP_TO_G15,500 (fixed)64 bytes: a single base field element Fp (big-endian). The top 16 bytes must be zero; the integer value must be strictly < p (BLS12-381 base field modulus).128 bytes: G1 affine point — 64-byte big-endian x, then 64-byte big-endian y (Fp coordinates, same canonical limb layout as other EIP-2537 G1 points).Pectra hardfork (EIP-2537, May 2025)Maps an Fp element to a point on BLS12-381 G1 using the SWU (Shallue–van de Woestijne–Ulas) map as defined in the EIP-2537 companion document. The returned point is on the G1 curve and lies in the prime-order subgroup (cofactor clearing is implicit for G1 because h₁ = 1). This precompile is not a full hash-to-curve primitive: it only implements Fp → G1. Callers that need bytes → G1 (for example, BLS message hashing) must first derive one or more Fp elements from the message in EVM (or off-chain), then compose maps and curve arithmetic as required by their protocol. On invalid input length or invalid field encoding (non-zero top 16 bytes, value ≥ p), all gas forwarded to the precompile is burned.

Threat Surface

BLS12_MAP_FP_TO_G1 is a low-level field-to-curve map: it assumes the caller has already chosen a concrete Fp representative and only answers whether that 64-byte encoding is canonical and what G1 point the enshrined SWU construction yields. It does not bind to application domains, message semantics, or random-oracle narratives — those are entirely caller-defined.

The dominant risks are cryptographic composition and strict encoding:

1. Incomplete hash-to-curve pipelines. Many developers want “hash message to G1” in one call. EIP-2537 intentionally omits bytes → Fp from this precompile because that step admits multiple standards and can be done efficiently in Solidity. That correct layering decision moves all responsibility for uniformity, domain separation, and multi-limb constructions to the contract author. Treating a single MAP_FP_TO_G1 invocation as the entire hash-to-curve — after a naive or single-limb field reduction of a digest — yields biased message points and breaks assumptions behind standard BLS security arguments (which typically rely on RFC 9380-style pipelines with two field elements mapped and combined).

2. Non-uniformity of a single SWU map. One SWU image point is not uniformly distributed on G1. For protocols that model the map as a random oracle, a single map is insufficient; the bias may be small but is cryptographically meaningful when proofs depend on uniform G1 challenges.

3. Canonical Fp encoding and failure economics. Like other BLS12 precompiles under EIP-2537, 64-byte big-endian limbs require 16 high zero bytes and value < p. Zero is valid and maps to a well-defined point. Any violation burns all forwarded gas — a smaller absolute stipend than pairing (5,500 gas) but still exploitable in tight loops or when contracts forward large gas budgets.

4. Cross-client determinism of SWU / square roots. Implementations must agree on every branch of SWU, including Fp square root (for example Tonelli–Shanks versus the p ≡ 3 (mod 4) fast path for BLS12-381). Divergence is a consensus fault class, separate from application-level misuse.


Smart Contract Threats

T1: Incomplete Hash-to-Curve Pipeline (High)

  • MAP_FP_TO_G1 is not a complete hash-to-curve function. It maps Fp → G1 only; it does not map arbitrary bytes → Fp.
  • A full hash-to-curve generally requires: (1) expand/hash the message to one or more field elements (with domain separation and correct length handling), (2) map each element to the curve (here via SWU), and (3) combine results (for G1, explicit cofactor clearing is not needed because h₁ = 1).
  • RFC 9380 hash-to-curve for BLS12-381 G1 typically uses two Fp elements, each passed through a map, then added — giving a distribution appropriate for random-oracle analyses.
  • Using one MAP_FP_TO_G1 call on a single field element derived from a hash (without the standard two-map construction) produces non-uniform points on G1, weakening the effective message hash in BLS-style schemes.
  • Safer pattern (conceptual): derive two canonical Fp encodings from the message per your protocol’s hash-to-field rules, call MAP_FP_TO_G1 twice, then BLS12_G1ADD to combine — matching the spirit of RFC 9380 / EIP-2537 usage guidance.

Why it matters: Miscomposed “hash-to-curve” breaks the algebraic and statistical assumptions auditors and proofs attach to BLS signatures and pairing-based protocols. The failure mode is often silent (no revert) while cryptographic strength drops.

T2: Non-Uniform Distribution for Single-Call Usage (Medium)

  • A single SWU map does not induce a uniform distribution on G1.
  • Security proofs that treat the message point as output of a random oracle are misaligned with single-map usage.
  • The bias can be subtle but matters wherever algebraic generic models assume uniform independent G1 points.

Why it matters: Protocol designers may underestimate the gap between “we called the map precompile” and “we implemented RFC 9380 hash-to-curve.” That gap becomes a design-level vulnerability in BLS deployments.

T3: Field Element Encoding Validation (Medium)

  • 64-byte big-endian Fp: top 16 bytes must be zero; interpreted integer must be < p.
  • Value = 0 is valid and maps to a specific G1 point (not a special-case error).
  • Value ≥ p fails even if lower limbs look plausible; non-zero high 16 bytes fail regardless of magnitude.
  • On any encoding error: all gas forwarded to 0x10 is burned.

Why it matters: Manual packing from uint256, keccak limbs, or off-chain tooling without mod p reduction and zero-extension produces bricked calls and griefing when paired with large forwarded gas. It also encourages unchecked call patterns that read stale buffers on failure.

T4: Gas Burning on Error (Low)

  • 5,500 gas is moderate; a single malicious input is rarely catastrophic alone.
  • In loops over many candidate field elements, cumulative burn and revert cascades can degrade liveness or DoS verification paths.
  • Contracts that use staticcall(gas(), 0x10, …) on untrusted encodings still risk disproportionate loss versus a capped stipend.

Why it matters: Error economics under EIP-2537 reward cheap client-side or on-chain pre-checks (length 64, limb shape, < p) before invoking the precompile.


Protocol-Level Threats

P1: Bytes-to-Field Left to the Caller (EIP Design)

EIP-2537 states that this mapping does not perform bytes → Fp because that step can be implemented many ways and can be done efficiently in the EVM. That split is correct for a minimal consensus interface but concentrates protocol risk in application code: every deployment must specify exactly how messages become Fp limbs, including domain separation and multi-output hashing where required.

P2: Deterministic SWU and Square-Root Semantics Across Clients

All execution clients must implement identical SWU behavior, including Fp square root branch selection. Different internal strategies (Tonelli–Shanks vs p ≡ 3 (mod 4) exponentiation) must agree on bit-identical outputs for all inputs. Any discrepancy is a consensus hazard, independent of Solidity misuse.

P3: Subgroup and On-Curve Guarantees for G1

The precompile’s output is specified to be on-curve and in the prime-order G1 subgroup. For BLS12-381 G1, cofactor 1 means there is no separate small-subgroup class on the curve image — the interesting subgroup story remains on G2 and in pairing entry points, not in MAP_FP_TO_G1 outputs themselves.


Edge Cases

Edge CaseBehaviorSecurity Implication
Input 64 zero bytes (u = 0)Valid; maps to a defined G1 point per specCallers must not assume “zero input” means error; protocol logic must treat 0 ∈ Fp like any other field element
Input represents p − 1Valid if encoding is canonical (< p)Extreme field values stress SWU / sqrt paths — rely on execution-spec-tests and client parity
Integer value ≥ pError; all forwarded gas burnedRequires mod p reduction before fixed-width serialization
Top 16 bytes non-zeroError; gas burnedCommon bug when concatenating ABI words without zeroing high limbs
Input length < 64 bytesError; gas burnedStrict length — no implicit padding
Input length > 64 bytesError; gas burnedExtra suffix bytes are not ignored
Valid Fp, boundary bit-lengthSuccess returns 128-byte G1 pointDownstream G1ADD / MSM / pairing still impose their own encoding rules

Real-World Exploits

No public, confirmed exploits targeting BLS12_MAP_FP_TO_G1 are known as of early 2026. The precompile shipped with Pectra (EIP-2537, May 2025) and has limited mainnet history compared to long-lived precompiles. The SWU map and hash-to-curve standards (RFC 9380) are well-studied; residual risk clusters in composition mistakes (single-map “hash-to-curve”) and in client implementation parity, not in a novel on-chain attack brand.

Precedent: Other curve precompiles have seen consensus-level validation bugs (for example CVE-2025-30147 on BN254 — different curve, same lesson: encoding and arithmetic paths must match the executable spec everywhere).


Attack Scenarios

Scenario A: Single MAP_FP_TO_G1 Used as Entire “Hash-to-Curve” for BLS

// VULNERABLE PATTERN: one field element, one map — not RFC 9380 / standard BLS message hash
pragma solidity ^0.8.0;
 
contract BiasedMessageMap {
    address internal constant MAP_FP_TO_G1 = address(0x10);
 
    /// @notice WRONG for production BLS: derives a single Fp from keccak256, maps once.
    function messageToG1(bytes32 domain, bytes calldata message)
        external
        view
        returns (bytes memory g1Point)
    {
        bytes32 h = keccak256(abi.encodePacked(domain, message));
        bytes memory fp64 = new bytes(64);
        // Pretend 32-byte hash left-padded to 64 bytes is a valid Fp encoding (still must be < p)
        assembly {
            mstore(add(fp64, 32), h) // lower 32 bytes; upper 32 bytes zero in this naive example
        }
 
        g1Point = new bytes(128);
        bool ok;
        assembly {
            ok := staticcall(
                gas(),
                MAP_FP_TO_G1,
                add(fp64, 32),
                64,
                add(g1Point, 32),
                128
            )
        }
        require(ok && returndatasize() == 128, "map failed");
        // Cryptographic issue: single-map pipeline → biased G1 message point vs two-map + add.
    }
}
 
// Failure / attack mode:
// 1. Signatures verify under this ad-hoc scheme but security proof assumptions fail.
// 2. Adversary may gain advantage vs protocols that assume uniform message points / ROM.
// Mitigation: implement proper hash-to-field (two limbs) + two MAP_FP_TO_G1 + BLS12_G1ADD (0x0B).

Scenario B: No Cheap Validation Before Precompile — Wasted Gas on Bad Encodings

// VULNERABLE PATTERN: unvalidated user-supplied "Fp" limb forwarded with huge gas stipend
pragma solidity ^0.8.0;
 
contract MapWithoutChecks {
    address internal constant MAP_FP_TO_G1 = address(0x10);
 
    function mapUntrusted(bytes calldata allegedFp64) external view returns (bytes memory out) {
        require(allegedFp64.length == 64, "length");
 
        out = new bytes(128);
        bool ok;
        assembly {
            ok := staticcall(
                gas(), // uncapped — burns all on EIP-2537 precompile error
                MAP_FP_TO_G1,
                allegedFp64.offset,
                64,
                add(out, 32),
                128
            )
        }
        require(ok, "map failed");
    }
}
 
// Failure / attack mode:
// 1. Attacker supplies 64 bytes with top limbs non-zero or value >= p.
// 2. Precompile burns all gas forwarded to 0x10; nested calls may OOG.
// Mitigation: cap stipend (~5500 + overhead); validate top-16-zero and < p when economical.

Mitigations

ThreatMitigationImplementation
T1: Incomplete hash-to-curveFollow RFC 9380-style construction: two Fp outputs from hash-to-field, two MAP_FP_TO_G1 calls, BLS12_G1ADDSpec the exact transcript hash; centralize in one audited library; cross-check test vectors against execution-spec-tests
T2: Single-map non-uniformityDo not rely on one SWU image as a random oracleSecurity reviews explicitly label “hash-to-curve” vs “field map” steps
T3: Bad Fp encodingEnforce len == 64, top 16 bytes == 0, value < p before staticcall when gas analysis favors itShared Fp serialization helpers; fuzz round-trip encodings
T4: Gas burningCap forwarded gas near 5,500 + overhead; avoid staticcall(gas(), 0x10, …) on untrusted inputWrapper contract with fixed stipend
P1: Caller-defined bytes→FpDocument domain separation and suite ID (if using RFC 9380 expand/message variants)Off-chain spec + on-chain comments at precompile call sites
P2: Client parityRun multi-client nodes on testnets; monitor advisoriesSame operational posture as other EIP-2537 primitives

Compiler/EIP-Based Protections

  • EIP-2537 (Pectra, May 2025): Defines BLS12_MAP_FP_TO_G1 at 0x10, 5,500 gas, strict 64-byte input and 128-byte G1 output, SWU map semantics, and burn all forwarded gas on failure.
  • Companion specification (referenced by EIP-2537): Canonical SWU and Fp decoding rules — implementations must match bit-for-bit across clients.
  • Solidity / Yul: No compiler-enforced hash-to-curve correctness; staticcall success, returndatasize == 128, and gas stipends are programmatic obligations.

Severity Summary

Threat IDCategorySeverityLikelihoodNotes
T1Smart contract / CryptographyHighMediumBiased message points when MAP_FP_TO_G1 substitutes for full hash-to-curve
T2Smart contract / Proof assumptionsMediumMediumROM / uniformity mismatch for single-map usage
T3Smart contract / EncodingMediumMediumNon-canonical Fp and ≥ p values; gas burn on error
T4Smart contract / EconomicsLowLow–Medium5,500 gas cap per call limits single-shot damage; loops amplify cost
P1Protocol / API layeringMediumN/ABytes→Fp complexity shifted to callers — correct but hazardous if misunderstood
P2Protocol / Client implementationHighLowSWU / sqrt divergenceconsensus fault (no known MAP_FP_TO_G1-specific incident)
P3Protocol / Curve semanticsLowN/AG1 cofactor 1 simplifies subgroup story vs G2

PrecompileRelationship
BLS12_MAP_FP2_TO_G2 (0x11)Fp² → G2 analogue; same caller-side hash-to-curve composition concerns on G2
BLS12_G1ADD (0x0B)Combines two G1 points — used after two field maps in standard hash-to-curve patterns
BLS12_G1MSM (0x0C)G1 multi-scalar multiplication; different validation rules vs bare G1ADD
BLS12_PAIRING_CHECK (0x0F)Consumes G1/G2 points from full verification pipelines that may include mapped points