Gnosis Safe – EIP-1271 Signatures with Gnosis Safe Off-Chain

eip-1271gnosis-safesafe-core

I am trying to generate an EIP-1271 contract signature off-chain, and propose a transaction using safe-api-kit. My first question is, is there support for creating EIP-1271 signatures using safe-core-sdk? I assume not simply because of this commit that is merged recently into develop which brings support for contract signatures. But if there are like helper(ish) functions with the current version I don't know of that I can use, it would be greatly appreciated.

Since I couldn't find any, I implemented my own signature by implementing the SafeSignature interface:

import { SafeSignature } from "@safe-global/safe-core-sdk-types";
import { addressToBytes32, intToBytes32 } from "./utils";

export const EIP1271_IMPL_CONTRACT_ADDRESS = "0x1E69533f104F7868DD280bf7E77b06F7De0b3063";

export class EIP1271SafeSignature implements SafeSignature {
    signer: string = EIP1271_IMPL_CONTRACT_ADDRESS;
    data: string = "0x00000000000000000000000000000000000000000000000000000000deadbeef";

    // EIP1271 implementing contract address
    private readonly r = addressToBytes32(EIP1271_IMPL_CONTRACT_ADDRESS);
    // offset of the dynamic data, for demo purposes we can put constant here
    private readonly s = intToBytes32(65);
    // signature type 0
    private readonly v = "00";
    // dynamic part of the signature in which can be any bytes, and will be sent to the EIP1271 implementing contract
    private dynamic = "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000deadbeef";

    staticPart(): string {
        return this.r + this.s.substring(2) + this.v;
    }

    dynamicPart(): string {
        return this.dynamic;
    }

    build() {
        return (this.staticPart() + this.dynamicPart()).toLowerCase();
    }
}

I know that offset (s part of the signature) requires a bit more work due to concatenation of multiple signatures into one, but currently, I am testing with only 1 threshold, and I am just trying to propose and execute a transaction, hence I hardcoded it as 65.

I first create a transaction as follows:

  const safeTransaction = await safeSdkOwner1.createTransaction({ 
    transactions: [{
      to: await owner1Signer.getAddress(),
      data: "0x",
      value: weiAmount,
    }],
  });

Then I get the Safe hash of this transaction:

  const safeTxHash = await safeSdkOwner1.getTransactionHash(safeTransaction);

Then I propose the transaction as following:

  const contractSignature = new EIP1271SafeSignature();
  await safeApiKit.proposeTransaction({
    safeAddress,
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: contractSignature.signer,
    senderSignature: contractSignature.build(),
  });

I receive the following error from the proposeTransaction method of safe-api-kit:

Error:
Signature=0x0000000000000000000000001e69533f104f7868dd280bf7e77b06f7de0b3063000000000000000000000000000000000000000000000000000000000000004100
for owner=0x1E69533f104F7868DD280bf7E77b06F7De0b3063 is not valid

And here is the signature I am getting by calling contractSignature.build():

0x0000000000000000000000001e69533f104f7868dd280bf7e77b06f7de0b3063000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000deadbeef

Any idea what I am doing wrong?

Versions

Safe: 1.3.0
Safe API Kit: 2.0.0
Safe Protocol Kit: 2.0.0

Best Answer

Safe natively supports EIP-1271 signatures. This page provides examples for signing, verifying, remotely fetching and troobleshooting EIP-1271 signatures. You can also find more information on the general way Safe handles different signature schemes on this page.

Please let me know if it helped solve your problem!

Thanks, Louis

Related Topic