ERC-8111

Bound Signatures

Binding y-parity compresses ECDSA signatures

StatusReview

TypeStandards Track

CategoryERC

Created2025-12-23

AuthorsWilliam Morriss (@wjmelements)

Last synced5/19/2026, 1:24:54 AM

Branchmaster

Upstreamethereum/ERCs/ERCS/erc-8111.md

Abstract

Recoverable ECDSA signatures can flip s and v while remaining valid, so they can be compressed to 64 bytes by restricting v.

Motivation

ECDSA signatures are often encoded with three parameters: v, r, and s. In the Solidity ABI encoding, this is 96 bytes. By eliminating the degree of freedom, v, the encoded size of a recoverable signature can be reduced to 64 bytes. Additionally, such signatures are not malleable.

Specification

Smart contracts accepting bound signatures MUST exclusively use 27 for v and MUST NOT accept any other value.

address signer = ecrecover(digest, 27, r, s);
require(signer != address(0));

ECDSA signatures MUST be bound before supplied to such contracts.

const SECP256K1_N: bigint = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n

function bind(sig: Signature, v: 27 | 28 = 27): Signature {
    if (sig.v === v) {
        return sig
    }
    const s = SECP256K1_N - sig.s
    return new Signature(sig.r, s, v)
}

Rationale

Another signature compression approach, ERC-2098, stores the y-parity bit in the most-significant bit of the low s. Bound signatures are preferable because they are valid inputs to the ecrecover precompile. They require less gas because they do not need to be unpacked by the smart contract.

A contract allowing both 27 and 28 reintroduces malleability. 27 was chosen over 28 to make the y-parity falsy.

Backwards Compatibility

Bound signatures are compatible with ecrecover if 27 is supplied for the v parameter. They cannot be used for transaction signatures because they permit high s, in violation of EIP-2.

Test Cases

SignerDigestrs
0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD10xb0922c37cafd247fe3ada4eb1d1e3735b7d2837437c1178e9af120d5352142700xdb7f75635124c807ec1f8b03e34cd76b633dc3a189e3c85fc5aee7e7d71df38c0x5f1e6c6edf21cacfc2acba2815b253b9048b894eec5aaf70343389bb596c48bc
0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD10xd92ff06caae7253883627416a425414d79e9003b91d6208add30e73735ef13c30xaa40efd534ac7f96b85babd7df9228fa131e8523115ca1ebc025698c37f3867d0xa4b8d3c650fe62e46a563aed681bfdd44d50452fa7712bd139f2bfba3aed59c9
0x6B93E3bB9C0780C0f9042346Ffc379530a5882c10xfa75eba87f076cf22489da7c53a651bb3869473f78d09d4814afb7ab2d54ed450xaf4a877600ab6d14ebac626830cf1063d624487932b3cc73a7cd98ae7fbf337f0xbc41d29acfcd3a1e7b5cb2dde1b85fe8882739312639b5f16d476a87584c040f

Reference Implementation

pragma solidity ^0.8.30;

library BoundSignatures {
    function recover(bytes32 digest, bytes32 r, bytes32 s) internal pure returns (address signer) {
        signer = ecrecover(digest, 27, r, s);
        require(signer != address(0));
    }
}

Security Considerations

Bound signatures are recoverable and not malleable.

Copyright and related rights waived via CC0.

Requires

Documents resolved from the normalized requires field.

Nothing here yet

No required documents from the emitted subset were resolved for this spec.

Required by

Documents in the emitted subset that declare this spec as a dependency.

Nothing here yet

No emitted documents currently depend on this spec.

Related documents

Simple metadata-based neighbors using family, type, category, and status overlap.