Problem with signature sent to Safe API POST request

62 Views Asked by At

A loom video of the problem faced: https://www.loom.com/share/4a054656f4bb4c329983394600058a01?sid=6de4f0c4-039e-4f45-9132-584f19cec13b

I create a signer from my Metamask Private Key and then create a signature from it like this:

const signer = new ethers.Wallet(PRIVATE_KEY as string, provider)
const safeInstance = new ethers.Contract(safeAddress, safeAbi, signer)
const safeTrxHash = await safeInstance.getTransactionHash(
      trxInput.to,
      trxInput.value,
      trxInput.data,
      trxInput.operation,
      trxInput.safeTxGas,
      trxInput.baseGas,
      trxInput.gasPrice,
      trxInput.gasToken,
      trxInput.refundReceiver,
      trxInput.nonce,
    )

const signature = (await signer.signMessage(safeTrxHash))
      .replace(/1b$/, '1f')
      .replace(/1c$/, '20')

The signature when passed onto the API route https://safe-transaction-mainnet.safe.global/api/v1/safes/0x493132b20De7b3e7825238414c204f8f30b17C7D/multisig-transactions/ provides the following error:

data: `{"nonFieldErrors":["Signer=0x2C7DC84b0aad92978B8D2F2fc72aBd6013cF6EB4 is not an owner or delegate. Current owners=['0xE28312CF65663803d1317c1ccf261E1edEC1FF6d']. Delegates=set()"]}

The signer that it says I provided is unknown to me but the address which is included in the current owners is the address i am actually providing. I was told that the error was probably due to how signature was generated.

Can anyone help me with this.

Loom Video: https://www.loom.com/share/4a054656f4bb4c329983394600058a01?sid=6de4f0c4-039e-4f45-9132-584f19cec13b

2

There are 2 best solutions below

0
On

For ethers v5.

This is a very common problem which is overlooked multiple times.

ethers.signMessage() abstracts how it perceives the message argument. If you pass an array like this ['0xab', '0xbc'], ethers will perceive it as Bytes, but if you pass a hash value represented as string 0xabbc, ethers will perceive it as string.

Hence, if you want to sign a hash using ethers.signMessage, you need to explicitly let ethers know by converting a hash into bytes array using arrayify.

To fix this problem you need to generate signature using:

const signature = (await signer.signMessage(ethers.utils.arrayify(safeTrxHash)))
      .replace(/1b$/, '1f')
      .replace(/1c$/, '20')

Sources: https://docs.ethers.org/v5/api/signer/#Signer-signMessage

0
On

You should use our API kit to interact with Safe services: https://docs.safe.global/sdk-api-kit