Precompile Summary

AddressNameGasInputOutputIntroducedBehavior
0x0BBLS12_G1ADD375 (fixed)256 bytes: two G1 affine points (128 bytes each). Each point is 64-byte big-endian x followed by 64-byte big-endian y (Fp elements). The top 16 bytes of each 64-byte coordinate must be zero (canonical limb layout for BLS12-381 base field).128 bytes: resulting G1 point: 64-byte x, then 64-byte y. The point at infinity is 128 zero bytes.Pectra hardfork (EIP-2537, May 2025)Performs point addition on the BLS12-381 G1 curve. Input points must lie on G1 or represent the point at infinity (all 128 zero bytes for that operand). No subgroup check is performed — this is by design per EIP-2537. On error (invalid encoding, point not on G1 and not infinity, wrong input length), all gas forwarded to the precompile is burned. On success, returns exactly 128 bytes.

Threat Surface

BLS12_G1ADD is a consensus-critical elliptic-curve primitive: it adds two affine G1 points on BLS12-381 and returns their sum. It does not interpret application semantics — no domains, authorization context, or proof-system binding — so correctness, failure handling, and cryptographic assumptions must be enforced by callers and by protocols that consume the outputs.

The threat surface has four dominant themes:

1. Punishing failure economics. Under EIP-2537, BLS12 precompiles burn all gas forwarded to the call on any error. That departs sharply from older patterns (for example, ECRECOVER returns empty on failure; BN256ADD returns empty with bounded gas). Contracts that forward large stipends — especially staticcall(gas(), 0x0B, …) — without cheap pre-validation can lose their entire remaining execution budget on a single malformed or off-curve input. Error handling is no longer “cheap failure”; it is a griefing and reliability lever.

2. Strict field encoding. Coordinates are 64-byte big-endian Fp elements with 16 high zero bytes and values strictly < p (the BLS12-381 base field modulus, 381 bits). A value can satisfy the zero high limbs yet still be ≥ p and remain invalid. Manual construction in Solidity, scripts, or off-chain signers that pad without canonical reduction is a recurring source of gas-burning failures and of logic bugs when callers assume any 256-byte blob is acceptable.

3. Subgroup policy versus developer mental models. EIP-2537 deliberately omits subgroup checks on G1ADD. For BLS12-381 G1, the curve cofactor is 1, so every point on the G1 curve lies in the prime-order subgroup; the omission is mathematically sound for pure G1 curve arithmetic and does not admit a small-subgroup point class on G1 the way G2 does. The risk is semantic: teams may treat “passed BLS12_G1ADD” as a blanket “BLS-safe / pairing-ready” guarantee. MSM and pairing paths under EIP-2537 apply different validation rules; copying G1 assumptions to G2ADD (cofactor ≠ 1) is especially dangerous (see 0x0D-BLS12_G2ADD).

4. Client and library maturity. As of March 2026, this family has roughly ten months of Ethereum mainnet history — far less than BN254 precompiles. CVE-2025-30147 showed that curve pipelines can ship subtle validation bugs that become consensus faults. BLS12-381 stacks (blst, gnark-crypto, arkworks, and others) are widely used but the Ethereum precompile binding layer is newer; parsing, infinity handling, and strict Fp checks must stay aligned with execution-spec-tests across all clients.


Smart Contract Threats

T1: No Subgroup Check by Design (High)

EIP-2537 deliberately omits subgroup checking for BLS12_G1ADD. The precompile accepts any validly encoded point on the G1 curve (plus the canonical infinity encoding).

  • G1 cofactor is 1. On BLS12-381 G1, every curve point is in the correct prime-order subgroup, so the lack of an explicit subgroup check does not create a small-subgroup input class on G1.
  • False sense of validation. Application code may infer “precompile validated my point” and feed outputs into components that expect points validated the same way as MSM or pairing entry points — those assumptions can be wrong and produce subtle integration bugs.
  • Asymmetry with MSM and pairing. BLS12_G1MSM performs subgroup checks on input points; G1ADD does not. Mixed pipelines that assume uniform validation without reading the spec are a recurring audit theme.
  • G1 versus G2 pattern porting. G2ADD shares the “no subgroup check” API shape but G2 has cofactor ≠ 1; the security story differs materially (see 0x0D-BLS12_G2ADD).

Why it matters: On G1 this is not a direct small-subgroup exploit surface, but it is a high-impact confusion hazard: wrong abstractions propagate into composite protocols and cross-curve copy-paste errors.

T2: Invalid Curve Point Handling (Medium)

Points not on the BLS12-381 G1 curve (and not the all-zero 128-byte infinity encoding for that point) are rejected. The call fails and all forwarded gas is burned.

  • Return handling is mandatory. Callers must check staticcall success and returndatasize == 128 on success. Ignoring failure and reading an output buffer yields stale memory — the same class of bug as unchecked BN256ADD calls.
  • Infinity encoding is strict. Only the canonical 128 zero bytes represent infinity; other “almost zero” encodings fail validation and burn gas.

Why it matters: Silent use of bogus curve data corrupts commitments, hashes, and downstream pairing inputs, breaking verifier soundness and enabling denial or manipulation of higher-level logic.

T3: Field Element Encoding Validation (Medium)

Each coordinate is a 64-byte big-endian Fp element: top 16 bytes zero, value < p. Values ≥ p are invalid even if high limbs are zero.

  • Non-canonical high limbs fail even when the mathematical integer could be reduced mod p.
  • Manual encoders must reduce mod p before fixed-width serialization; “pad to 64 bytes” without reduction is unsafe.

Why it matters: Encoding mistakes cause gas-burning failures and, when combined with poor error handling, stale-output misuse; adversaries can also grief with cheap-to-craft invalid encodings if calls use large forwarded gas.

T4: Gas Burning on Error (Medium)

Unlike ECRECOVER (empty return) or BN256ADD (empty return, fixed low gas), BLS12 precompiles under EIP-2537 burn all gas forwarded to the precompile on error.

  • staticcall(gas(), …) with attacker-controlled curve data can wipe the callee’s remaining gas on failure.
  • Contracts should validate length and encoding before the call, or cap the stipend (for example, 375 plus overhead) instead of forwarding unbounded gas.

Why it matters: Failure cost scales with forwarded gas, enabling griefing and breaking contracts that assumed precompile failures are inexpensive.


Protocol-Level Threats

P1: Newest Precompile Family — Limited Mainnet Battle-Testing

BLS12_G1ADD shipped with Pectra (EIP-2537, May 2025). Compared to BN254 precompiles, operational history on Ethereum mainnet is short — on the order of ten months as of March 2026. Latent client bugs, spec-edge discoveries under fuzzing, and cross-client divergence are more plausible in early deployment years than for decade-old primitives, even with strong execution-spec-tests coverage.

P2: Implementation and Library Risk (CVE-2025-30147 Precedent)

CVE-2025-30147 on BN254 precompiles showed that curve operation implementations can confuse subgroup checks with on-curve validation (or otherwise mishandle points), producing consensus-critical divergence in a client. BLS12-381 libraries are mature in isolation, but the EVM precompile integration path is newer; refactors, optimizations, or library swaps in clients reopen the same validation risk class.

P3: No-Subgroup-Check Precedent and G1/G2 Confusion

The EIP-2537 choice is correct for G1 given cofactor 1, but it is easy to over-generalize when porting patterns to G2 or to off-chain BLS APIs that do perform cofactor clearing. Documentation and audits must distinguish on-curve, subgroup-checked, and pairing-ready points — failures here are specification-understanding bugs at protocol scale.


Edge Cases

Edge CaseBehaviorSecurity Implication
Point at infinity (128 zero bytes) + PReturns P (identity)Callers must treat all-zero 128 bytes as infinity, not unconstrained zeros
P + (−P)Returns point at infinity (128 zero bytes)Valid; downstream logic must accept infinity where the math allows
P + P (doubling)Handled as addition of identical affine pointsMust match EIP-2537 and client tests; exercise doubling vectors in CI
Input length < 256 bytesError; all forwarded gas burnedStrict length — no silent padding
Input length > 256 bytesError; all forwarded gas burnedExtra bytes are not ignored
Coordinate ≥ field modulusError; gas burnedCanonical Fp reduction required before encoding
Top 16 bytes of a coordinate non-zeroError; gas burnedViolates canonical Fp encoding
Point on G1 “wrong subgroup”Not checked — and for G1, cofactor 1 makes this a non-issueSafe for G1 arithmetic; confusing when compared to G2 or to MSM subgroup checks
Empty input (0 bytes)Error; gas burnedInvalid length
Valid encoding, point not on G1Error; gas burnedSeparate encoding validity from curve membership

Real-World Exploits

Exploit 1: No Known Exploits Specific to BLS12_G1ADD (as of Early 2026)

Root cause: N/A — there is no public, confirmed exploit chain targeting BLS12_G1ADD specifically. The precompile is new; on-chain usage is still growing.

Details: Ethereum execution-spec-tests include extensive vectors for EIP-2537 curve operations. Multiple client teams and auditors have reviewed BLS12-381 integrations. The absence of known exploits is not a proof of absence of bugs — BN254 precompiles operated for years before CVE-2025-30147 highlighted validation divergence across libraries.

Precompile’s role: BLS12_G1ADD is a building block for on-chain BLS12-381 arithmetic. A future client bug in addition/encoding could affect any protocol that depends on 0x0B for verifier or aggregation logic.

Impact: No confirmed mainnet theft or split attributed to G1ADD to date; potential impact would mirror other consensus-critical precompiles (verifier unsoundness or network divergence).

References:


Exploit 2: CVE-2025-30147 — BN254 Validation Bug as Precedent for BLS12 Client Risk

Root cause: A client implementation (Hyperledger Besu, affected versions 24.7.1–25.2.2) did not fully validate BN254 precompile inputs before arithmetic, while other major clients did. Off-curve points could yield incorrect curve results, producing state root divergence (CVSS 4.0 score 8.7). Fixed in Besu 25.3.0 / besu-native 1.3.0.

Details: The defect concerned alt_bn128 precompiles, not BLS12-381. The lesson transfers: curve precompile code paths must match the executable spec for encoding, on-curve checks, and infinity handling — any skew is a consensus hazard. BLS12-381 has a larger field and different serialization than BN254, widening parsing and reduction surface area if clients disagree.

Precompile’s role: BLS12_G1ADD was not involved in CVE-2025-30147. It is cited as the closest real-world precedent for “curve precompile + validation mistake → divergence.”

Impact: Consensus / split risk on networks dominated by a buggy client; on heterogeneous Ethereum mainnet, enshrined divergence was limited, but the vulnerability class is practical, not theoretical.

References:


Attack Scenarios

Scenario A: Large Forwarded Gas to BLS12_G1ADD Without Cheap Validation

// VULNERABLE PATTERN: forwards all remaining gas; malformed input burns it all (EIP-2537)
pragma solidity ^0.8.0;
 
contract RiskyG1Add {
    address internal constant BLS12_G1ADD = address(0x0B);
 
    function addG1(bytes calldata input) external returns (bytes memory) {
        require(input.length == 256, "length"); // length alone does not imply valid Fp / on-curve
 
        bytes memory out = new bytes(128);
        bool ok;
        assembly {
            ok := staticcall(
                gas(), // forwards entire remaining gas — dangerous on EIP-2537 failure
                BLS12_G1ADD,
                input.offset,
                256,
                add(out, 32),
                128
            )
        }
        require(ok, "g1add failed");
        // Also assert returndatasize() == 128 in assembly-heavy code paths.
        return out;
    }
}
 
// Failure / attack mode:
// 1. Attacker supplies 256 bytes with invalid Fp limbs or off-curve coordinates.
// 2. Precompile errors; all gas forwarded to 0x0B is burned.
// 3. Victims may OOG; griefing scales with gas limit and uncapped stipend.
// Mitigation: cap stipend (~375 + overhead); validate encodings before call where economical.

Scenario B: Ignoring Return Status and Using Stale Memory

// VULNERABLE PATTERN: ignores staticcall success and effective return length
pragma solidity ^0.8.0;
 
contract UnsafeG1Add {
    address internal constant BLS12_G1ADD = address(0x0B);
 
    function addG1Unchecked(
        bytes32 x1_hi, bytes32 x1_lo,
        bytes32 y1_hi, bytes32 y1_lo,
        bytes32 x2_hi, bytes32 x2_lo,
        bytes32 y2_hi, bytes32 y2_lo
    ) external view returns (bytes32 ox_hi, bytes32 ox_lo, bytes32 oy_hi, bytes32 oy_lo) {
        bytes memory input = abi.encodePacked(
            x1_hi, x1_lo, y1_hi, y1_lo,
            x2_hi, x2_lo, y2_hi, y2_lo
        );
        bytes memory output = new bytes(128);
 
        assembly {
            pop(staticcall(
                gas(),
                BLS12_G1ADD,
                add(input, 32),
                256,
                add(output, 32),
                128
            ))
            // BUG: success ignored. On failure, returndata may be empty; buffer may be stale/zero.
        }
 
        assembly {
            ox_hi := mload(add(output, 32))
            ox_lo := mload(add(output, 64))
            oy_hi := mload(add(output, 96))
            oy_lo := mload(add(output, 128))
        }
    }
}
 
// Failure mode:
// 1. Provide off-curve or invalidly encoded coordinates (still 256 bytes).
// 2. Precompile fails; gas burned; staticcall success = false.
// 3. Contract still reads `output` as a valid G1 point and continues verification.

Mitigations

ThreatMitigationImplementation
T1: Subgroup / API confusionDocument G1 cofactor = 1 vs G2; never assume G1ADD implies the same checks as MSM or pairingArchitecture reviews; explicit comments at call sites; read EIP-2537 for per-precompile rules
T2: Stale outputCheck success and returndatasize == 128require(ok); assembly returndatasize() check; returndatacopy into a fresh buffer
T3: Bad Fp encodingEnforce top-zero limbs and < p before call when economicalShared serialization helpers; property tests against execution-spec-tests vectors
T4: Gas burningCap forwarded gas (375 + small overhead)Avoid staticcall(gas(), 0x0B, …) for untrusted input; validate length 256 before call
P1–P2: Client riskDiversify clients on critical networks; track security advisoriesSame operational response pattern as post-CVE-2025-30147
GeneralCentralize BLS12 calls in one audited moduleSingle wrapper for G1ADD / G1MSM / pairing with uniform error and gas policy

Compiler/EIP-Based Protections

  • EIP-2537 (Pectra, May 2025): Defines BLS12_G1ADD at 0x0B, 375 gas, input/output layouts, infinity encoding, no subgroup check on G1ADD, and burn all forwarded gas on failure.
  • Execution-spec-tests: Conformance vectors for cross-client agreement; they do not substitute for client version hygiene or operational monitoring.
  • Solidity / Yul: No compiler-enforced check of precompile success or return length — mitigations are purely programmatic (staticcall result, returndatasize, gas stipends).

Severity Summary

Threat IDCategorySeverityLikelihoodReal-World Precedent
T1Smart Contract / Spec understandingHighMediumNo G1 small-subgroup exploit (cofactor 1); BLS API confusion is a recurring audit theme
T2Smart ContractMediumMediumUnchecked precompile calls — stale memory (BN256ADD pattern)
T3Smart ContractMediumMediumNon-canonical Fp encodings and ≥ p values with zero high limbs
T4Smart Contract / EconomicsMediumMediumEIP-2537 gas burn on error — griefing with high stipends
P1Protocol / OperationalMediumN/A (time-dependent)~10 months mainnet exposure as of March 2026 vs BN254
P2Protocol / ClientHighLowCVE-2025-30147 (BN254 / Besu) — validation bugs → consensus divergence
P3Protocol / EducationMediumMediumG1 vs G2 cofactor asymmetry — pattern-porting bugs

PrecompileRelationship
BLS12_G1MSM (0x0C)Multi-scalar multiplication on G1; performs subgroup checks on points — different trust assumptions than G1ADD
BLS12_G2ADD (0x0D)G2 addition; cofactor ≠ 1no subgroup check is far more dangerous than on G1
BLS12_PAIRING_CHECK (0x0F)Pairing-based verification consuming G1/G2 points from broader pipelines
BN256ADD (0x06)Earlier curve addition on alt_bn128; empty return and different gas semantics vs EIP-2537 burn-on-error
BLS12_MAP_FP_TO_G1 (0x10)Field-to-G1 map; outputs may feed G1ADD in hash-to-curve constructions