Skip to main content

Try it Live

Run BLS12-381 examples in the interactive playground

BLS12-381 Precompiles

EIP-2537 defines BLS12-381 precompiled contracts for the EVM.
NOT on Mainnet - These precompiles are proposed but NOT activated on Ethereum mainnet. For execution layer zkSNARKs, use BN254 precompiles (addresses 0x06-0x08) which ARE available on mainnet.

Status

NetworkStatus
Ethereum Mainnet❌ Not activated
Sepolia✅ Available for testing
Some L2s⚠️ Check individual L2 docs

Precompile Addresses

If/when activated, the precompiles occupy addresses 0x0b through 0x13:
AddressNameOperation
0x0bBLS12_G1ADDG1 point addition
0x0cBLS12_G1MULG1 scalar multiplication
0x0dBLS12_G1MSMG1 multi-scalar multiplication
0x0eBLS12_G2ADDG2 point addition
0x0fBLS12_G2MULG2 scalar multiplication
0x10BLS12_G2MSMG2 multi-scalar multiplication
0x11BLS12_PAIRINGPairing check
0x12BLS12_MAP_FP_TO_G1Map field element to G1
0x13BLS12_MAP_FP2_TO_G2Map Fp2 element to G2

Gas Costs

G1 Operations

OperationGas Cost
G1ADD500
G1MUL12,000
G1MSM (base)12,000
G1MSM (per point)Discount schedule

G2 Operations

OperationGas Cost
G2ADD800
G2MUL45,000
G2MSM (base)45,000
G2MSM (per point)Discount schedule

Pairing

OperationGas Cost
Pairing (base)115,000
Pairing (per pair)23,000

Hash-to-Curve

OperationGas Cost
MAP_FP_TO_G15,500
MAP_FP2_TO_G2110,000

Input/Output Formats

G1 Point (Uncompressed)

| x-coordinate | y-coordinate |
|   64 bytes   |   64 bytes   |
Total: 128 bytes (padded from 96)

G2 Point (Uncompressed)

| x.c0 | x.c1 | y.c0 | y.c1 |
|  64  |  64  |  64  |  64  |
Total: 256 bytes (padded from 192)

Scalar

| scalar |
| 32 bytes |

Operation Details

G1ADD (0x0b)

Add two G1 points. Input: 256 bytes (two G1 points) Output: 128 bytes (one G1 point)
// Pseudocode
function g1Add(bytes memory input) returns (bytes memory) {
    G1Point p1 = decodeG1(input[0:128]);
    G1Point p2 = decodeG1(input[128:256]);
    return encodeG1(p1 + p2);
}

G1MUL (0x0c)

Multiply G1 point by scalar. Input: 160 bytes (G1 point + 32-byte scalar) Output: 128 bytes (one G1 point)
function g1Mul(bytes memory input) returns (bytes memory) {
    G1Point p = decodeG1(input[0:128]);
    uint256 scalar = uint256(bytes32(input[128:160]));
    return encodeG1(p * scalar);
}

G1MSM (0x0d)

Multi-scalar multiplication on G1. Input: Variable (pairs of G1 point + scalar) Output: 128 bytes (one G1 point) Computes: Σ sᵢ·Pᵢ

PAIRING (0x11)

Pairing check on multiple pairs. Input: Variable (pairs of G1 and G2 points) Output: 32 bytes (boolean: 1 if check passes, 0 otherwise) Verifies: e(P₁, Q₁) · e(P₂, Q₂) · ... · e(Pₙ, Qₙ) = 1
function pairingCheck(bytes memory input) returns (bool) {
    // Input: n * (128 + 256) = n * 384 bytes
    uint256 n = input.length / 384;

    G1Point[] memory g1Points = new G1Point[](n);
    G2Point[] memory g2Points = new G2Point[](n);

    for (uint256 i = 0; i < n; i++) {
        g1Points[i] = decodeG1(input[i*384:i*384+128]);
        g2Points[i] = decodeG2(input[i*384+128:i*384+384]);
    }

    return multiPairing(g1Points, g2Points) == GT.identity();
}

Use Cases (When Available)

BLS Signature Verification

// Verify BLS signature in smart contract
function verifyBLSSignature(
    bytes memory publicKey,   // 128 bytes G1
    bytes memory message,     // arbitrary
    bytes memory signature    // 256 bytes G2
) public view returns (bool) {
    // Hash message to G2
    bytes memory messagePoint = mapToG2(hashToFp2(message));

    // Pairing check: e(pk, H(m)) == e(G1, sig)
    // Equivalently: e(pk, H(m)) · e(-G1, sig) == 1
    bytes memory input = abi.encodePacked(
        publicKey,
        messagePoint,
        G1_GENERATOR_NEG,
        signature
    );

    (bool success, bytes memory result) = BLS12_PAIRING.staticcall(input);
    return success && abi.decode(result, (bool));
}

Aggregated Signature Verification

function verifyAggregatedSignature(
    bytes[] memory publicKeys,
    bytes memory message,
    bytes memory aggregatedSignature
) public view returns (bool) {
    // Aggregate public keys
    bytes memory aggPk = publicKeys[0];
    for (uint256 i = 1; i < publicKeys.length; i++) {
        aggPk = g1Add(aggPk, publicKeys[i]);
    }

    return verifyBLSSignature(aggPk, message, aggregatedSignature);
}

Error Conditions

Precompiles return error (consume all gas) for:
  • Invalid point encoding
  • Point not on curve
  • Point not in correct subgroup
  • Invalid scalar (> field modulus)
  • Input length mismatch

Comparison with BN254

FeatureBLS12-381BN254
Security128-bit~100-bit
Mainnet❌ Not yet✅ Available
Pairing gas115,000 + 23,000/pair45,000 + 34,000/pair
Use caseConsensus layerzkSNARKs, DeFi