1

I have a Safe with the address 0x143... This safe has a delegate which is an EOA with public address 0xBEf.... this delegate should be able to propose a transaction to the safe it was assigned to as a delegate. However I am having problems with the signature.

My current approach is:

  1. Initialize a protocol kit with the safe owner address (0xBE...) and no signer attached.
  2. Create the transaction using the protocol kit (0xBE...)
  3. Extract transaction hash from the transaction using the protocol kit (0xBE...)
  4. Sign the transaction hash using an ethers wallet loaded with the private key of the delegate (public address 0x14).
  5. Propose the transaction with the apiKit, example below
  const parentSafe = await Safe.init({
    provider: RPC_URL,
    safeAddress: PARENT_SAFE_ADDRESS,
  });
  const safeTransaction = await parentSafe.createTransaction({
    transactions: topUpTransactions,
  });
  const safeTxHash = await parentSafe.getTransactionHash(safeTransaction);
  const messageArray = ethers.getBytes(safeTxHash);
  const senderSignature = await delegateWallet.signMessage(messageArray);


  await apiKit.proposeTransaction({
    safeAddress: PARENT_SAFE_ADDRESS, // 0x143...
    safeTransactionData: safeTransaction.data,
    safeTxHash,
    senderAddress: signerAddress, // 0xBEf...
    senderSignature: senderSignature, // Signed by 0xBEf
  });

This result in the error that the signer is not an owner or a delegate.

Signer=0xa4E5aae4C1748cc8CA02985e3907072d02F7666F is not an owner or delegate

The error indicates that the signer was 0xa4E.... This is not an address that I have seen before.

I have confirmed that the EOA 0xBEf... is indeed a delegate of the Safe (confirmed in the error message).

I have also confirmed that the recovered address from the signature matches the delegate wallet 0xBEf....

Has anyone encountered an error such as this or have some guides or examples on how to propose transaction to a safe through the delegate account?

1
  • Hey Tthug, thanks for the great question! Let me check internally. Commented Sep 2 at 10:41

1 Answer 1

0

Thanks for your question. I hope I can help you.

You can find a reference implementation in dispatch.ts of this PR.

Here is the code for reference:

// We have to manually sign because sdk.signTransaction doesn't support delegates
export const dispatchDelegateTxSigning = async (safeTx: SafeTransaction, wallet: ConnectedWallet) => {
  const sdk = await getSafeSDKWithSigner(wallet.provider)

  let signature: SafeSignature
  if (isHardwareWallet(wallet)) {
    const txHash = await sdk.getTransactionHash(safeTx)
    signature = await sdk.signHash(txHash)
  } else {
    signature = await sdk.signTypedData(safeTx)
  }

  safeTx.addSignature(signature)

  return safeTx
}

So you are correct to sign the txHash manually, but you have to use another method. sdk is a simple instance of the protocol kit. Make sure to connect your delegate's wallet to the protocol kit. You can either hand wallet.provider as the provider to the init function, or you can hand the provider over in the connect function, as exemplified here.

Let me know if this answers your question (please mark your questions as answered) or if you encounter further issues.

2
  • Thank you. I got this to work for me the thing that I was missing was to sign with the safe methods. I already had a protocolKit that was initialized to the parent's safe but also had the delegate private key. After using the sdk.signHash and adding the signature to the transaction. The updated process works for me: - Initialize sdk with parent safe address and delegate signer - use sdk to create transaction - use sdk to get and sign transaction hash - add signature to the transaction - propose transaction using apiKit
    – tthug
    Commented Sep 10 at 13:01
  • Perfect, that looks like a good process to me. Commented Sep 12 at 9:07

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.