I want to build an ink! contract where some functions need to verify messages signed by the caller.

In ink! contract there is a helper function named ink_env::ecdsa_recover(), which seems helpful in my use case. However, I am not sure how to sign ecdsa messages using polkadot.{js}. I can only generate sr25519 signatures.

An alternative is to verify sr25519 signatures in the contract instead of ecdsa signatures. However, it seems that verifying sr25519 signatures requires the caller's public key, but I only have the caller's AccountId (or address). Is there a way to convert the address to the public key in ink! contract?

2 Answers 2


The js libs supports the following crypto types & signatures - sr25519, ed25519, ecdsa (Substrate 32-byte public) & ethereum (Moonbeam-like, 20-byte public).

So you can add a pair to the keyring using the specified type and then sign the data. A contrived example below.

/* create a keyring */
const keyring = new Keyring()

/* create a pair on the keyring */
const pair = keyring.addFromMnemonic(
  /* mnemonic */
  "abandon ...", 
  /* any metadata, user-specified */
  { name: "test" }, 
  /* pair type - needs to be specified, otherwise keyring default */
  { type: "ecdsa" }

/* sign some data */
const sig_uint8array = pair.sign("message")

Schnorr signatures as for example sr25519 do not communicate their public key. So you either supply the public key separately in addition to the signature or you use ECDSA over the secp256k1 curve. In the latter case you can then use ink_env::ecdsa_recover().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.