--- eip: 8111 title: Bound Signatures description: Binding y-parity compresses ECDSA signatures author: William Morriss (@wjmelements) discussions-to: https://ethereum-magicians.org/t/erc-8111-bound-signatures/27308 status: Review type: Standards Track category: ERC created: 2025-12-23 --- ## 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. ```solidity address signer = ecrecover(digest, 27, r, s); require(signer != address(0)); ``` ECDSA signatures MUST be bound before supplied to such contracts. ```ts 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](./eip-2098.md), 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](./eip-2.md). ## Test Cases | Signer | Digest | `r` | `s` | | ------ | ------ | --- | --- | | `0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1` | `0xb0922c37cafd247fe3ada4eb1d1e3735b7d2837437c1178e9af120d535214270` | `0xdb7f75635124c807ec1f8b03e34cd76b633dc3a189e3c85fc5aee7e7d71df38c` | `0x5f1e6c6edf21cacfc2acba2815b253b9048b894eec5aaf70343389bb596c48bc` | | `0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1` | `0xd92ff06caae7253883627416a425414d79e9003b91d6208add30e73735ef13c3` | `0xaa40efd534ac7f96b85babd7df9228fa131e8523115ca1ebc025698c37f3867d` | `0xa4b8d3c650fe62e46a563aed681bfdd44d50452fa7712bd139f2bfba3aed59c9` | | `0x6B93E3bB9C0780C0f9042346Ffc379530a5882c1` | `0xfa75eba87f076cf22489da7c53a651bb3869473f78d09d4814afb7ab2d54ed45` | `0xaf4a877600ab6d14ebac626830cf1063d624487932b3cc73a7cd98ae7fbf337f` | `0xbc41d29acfcd3a1e7b5cb2dde1b85fe8882739312639b5f16d476a87584c040f` | ## Reference Implementation ```solidity 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 Copyright and related rights waived via [CC0](../LICENSE.md).