Some context.

  • The frontend right now is using wagmi under the hood, we are using the signMessageAsync method to generate a signature. Code is below
const { signMessageAsync } = useSignMessage()
const signature = await signMessageAsync({
  message: ethers.utils.arrayify(...),
  • We are 100% that we are passing the right parameters in the value that is passed to arrayify since hot wallets and wallet connect with ledger live is working. Only metamask with ledger is not working.

  • The recovery method on the smart contract is below.

require(ECDSA.recover(<eth signed hash>, sig) == msg.sender, "Invalid signature!");
  • We noticed that the last bits of the signature is 00 or 01. So we tried to adjust the v parameter with the function below to make sure it is of the right value.
function _adjustV(v: number): number {
  const chainId = <chain id of current network - we use public env vars for this>
  const baseV = chainId * 2 + 35
  if (v % 2 === 0) {
    return baseV
  } else {
    return baseV + 1

It still doesn't work. Is there a special workaround needed for metamask with ledger to work?

  • I have come across a very similar issue a while ago and posted an answer to it here: ethereum.stackexchange.com/questions/111610/… Feb 16, 2023 at 14:50
  • thanks for commenting. didn't quite get that. the wagmi library is actually just using etherjs under the hood. you mean there's an extra step needed here with the use of split signature? I did use it when I tried to adjust v and then join it again. Feb 16, 2023 at 15:16
  • 1
    You only need to replace the value for v in order to make the Ledger signatures work. Basically: if v is 0, then replace it with 27. If v is 1, then replace it with 28. Feb 16, 2023 at 15:30
  • Make sure your logic does not affect other values of v. You only need to change v for inputs {0,1}. Feb 16, 2023 at 15:32

1 Answer 1


As recommended in the comments, it seems the formula of chain * 2 + 35 is not needed. It's really just a literal change of 0 > 27 and 1 > 28.

final code is shown below:

The adjust function:

function _adjustV(v: number): number {
  if (v === 0) {
    return 27
  } else if (v === 1) {
    return 28
  } else {
    return v

The signature modification:

const { v, r, s } = ethers.utils.splitSignature(signature)
const adjustedV = _adjustV(v)
const adjustedSignature = ethers.utils.joinSignature({r, s, v: adjustedV})

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.