signaturesecp256k1_sign

On-chain secp256k1 ECDSA signing

Sign messages on-chain using Mercury EVM's secp256k1 signing precompile.

Overview

The secp256k1 signing precompile at address 0x69 creates ECDSA signatures on-chain. The message is hashed with the EIP-191 personal-sign prefix before signing, producing a 65-byte signature (r + s + v) compatible with ecrecover and standard Ethereum signature verification.

Precompile Address

0x0000000000000000000000000000000000000069

Input Encoding

Field
Size
Description

secret_key

32 bytes

secp256k1 private key

message_hash

32 bytes

Keccak-256 hash of the EIP-191 prefixed message

The input is the concatenation of secret_key (32 bytes) + message_hash (32 bytes), for a total of 64 bytes.

circle-info

You must hash the message yourself before calling the precompile. The precompile expects the EIP-191 prefixed message hash: keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)

Output Format

Field
Size
Description

r

32 bytes

Signature r component

s

32 bytes

Signature s component

v

1 byte

Recovery ID (27 or 28)

Total output: 65 bytes.

Parameters

Parameter
Type
Required
Description

secret_key

[u8; 32]

Yes

32-byte secp256k1 private key

message_hash

[u8; 32]

Yes

32-byte keccak256 hash of EIP-191 prefixed message

Examples

Basic Usage

Extract Signature Components

Sign Multiple Messages

Sign Structured Data

How It Works

  1. Hash message -- You apply the EIP-191 personal-sign prefix and keccak256 hash:

  2. Encode parameters -- Concatenate the 32-byte private key and 32-byte message hash

  3. Call precompile -- Issues an eth_call to address 0x69 with 3000 gas

  4. Sign hash -- Precompile performs ECDSA signing on the secp256k1 curve

  5. Return signature -- Returns 65-byte signature (r + s + v)

Gas Cost

Fixed gas cost: 3000 gas

The cost is constant regardless of message length (since the message is hashed before signing).

EIP-191 Message Hashing

The precompile expects the standard EIP-191 personal-sign message hash:

This ensures compatibility with standard Ethereum message signing (e.g., MetaMask's personal_sign).

Signature Format

The returned signature is 65 bytes:

Component
Offset
Size
Description

r

0

32 bytes

Signature r value

s

32

32 bytes

Signature s value

v

64

1 byte

Recovery ID (27 or 28)

This format is compatible with ecrecover and standard Ethereum signature verification.

Notes

  • Uses secp256k1 curve (same as Ethereum)

  • You must hash the message with EIP-191 prefix before calling the precompile

  • Signatures are non-deterministic (random k value)

  • Compatible with MetaMask and other Ethereum wallets

  • Can be verified on-chain using the ecrecover precompile

Warnings

  • Private key security -- Never expose or log private keys

  • Message format -- Ensure messages are hashed correctly with EIP-191 prefix before sending to the precompile

  • Signature malleability -- Standard ECDSA signatures are malleable (use EIP-2098 compact signatures if needed)

  • Non-deterministic -- Multiple signatures of the same message will differ due to random k values

See Also

Last updated