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({
    safeTransactionData: safeTransaction.data,
    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():


Any idea what I am doing wrong?


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

2 Answers 2


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

  • Hey Louis, thanks for the answer! It unfortunately did not. Because the page you linked shows an example for the client-side signing with WalletConnect. But I need this to be done on the server-side. Commented Jan 28 at 20:28

After going through their codebase the problem seems to be that Safe Transaction Service is still trying to call the old EIP-1271 interface isValidSignature(bytes,bytes) instead of isValidSignature(bytes32,bytes). I added the old version into my EIP-1271 contract and proposeTransaction is working now.

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.