Skip to content

Conversation

@paulbalaji
Copy link

@paulbalaji paulbalaji commented Dec 2, 2025

Summary

Fixes a bug where an address that is both a Safe owner AND registered as a delegate/proposer cannot participate in multi-signature transactions.

When a user is both an owner and a proposer for a Safe, any transaction they create becomes "stuck" - other owners cannot add their confirmations because the transaction service incorrectly applies the delegate signature restriction.

Workaround

Users can remove the owner from the Proposers list. However, this should still be fixed - the UI allows this configuration without warning, the error message is confusing, and being a delegate shouldn't reduce an owner's capabilities.

Root Cause Analysis

The Bug

In SafeMultisigTransactionSerializer.validate(), the delegate check doesn't account for addresses that are both owners AND delegates:

# Before (buggy)
if owner in delegates and len(parsed_signatures) > 1:
    raise ValidationError("Just one signature is expected if using delegates")

This triggers whenever ANY signer in the transaction is in the delegates list, even if they're also an owner.

How the Safe Wallet Triggers This

Looking at safe-wallet-monorepo/apps/web/src/services/tx/tx-sender/dispatch.ts, the dispatchTxProposal function handles both new transactions AND confirmations on existing transactions:

/**
 * Propose a transaction
 * If txId is passed, it's an existing tx being signed
 */
export const dispatchTxProposal = async ({
  chainId,
  safeAddress,
  sender,
  safeTx,
  txId,  // <-- existing tx being confirmed
  origin,
}): Promise<TransactionDetails> => {

When a user clicks "Confirm" on an existing transaction, the wallet:

  1. Loads the existing transaction with its signatures
  2. Adds the new signer's signature
  3. Re-POSTs to the propose endpoint (/v1/safes/{address}/multisig-transactions/) with ALL accumulated signatures

This means confirmations go through SafeMultisigTransactionSerializer, not SafeMultisigConfirmationSerializer.

The Failure Scenario

  1. User A (0x0247...) is both an owner (1 of 6) and a proposer for the Safe
  2. User A creates a transaction and signs it (1/3 signatures needed)
  3. User B (0xb85f...), a different owner, clicks "Confirm"
  4. Wallet re-POSTs with both signatures (A's + B's)
  5. Backend iterates through signatures, finds User A is in delegates
  6. Since len(parsed_signatures) > 1 (now 2), throws: "Just one signature is expected if using delegates"
  7. Transaction is stuck at 1/3 - can never reach threshold

The Fix

# After (fixed)
if owner in delegates and owner not in safe_owners and len(parsed_signatures) > 1:
    raise ValidationError("Just one signature is expected if using delegates")

The additional owner not in safe_owners check ensures:

  • Pure delegates (not owners): Still restricted to single signature ✓
  • Owner-delegates (both owner AND delegate): Treated as owners, no restriction ✓

Test Plan

  • Added test_post_multisig_transactions_with_owner_who_is_also_delegate for v1 API
  • Added test_post_multisig_transactions_with_owner_who_is_also_delegate for v2 API
  • Existing delegate tests still pass (pure delegates remain restricted)
  • Manual testing with a Safe where an owner is also a proposer

🤖 Generated with Claude Code


Note

Adjust delegate restriction to exclude Safe owners from the single-signature rule and add tests for v1/v2 APIs.

  • Backend
    • Update SafeMultisigTransactionSerializer.validate in safe_transaction_service/history/serializers.py to only enforce the delegate single-signature rule when signer is in delegates and not in safe_owners.
  • Tests
    • Add test_post_multisig_transactions_with_owner_who_is_also_delegate to history/tests/test_views.py and history/tests/test_views_v2.py to verify owner-delegates can submit multiple signatures successfully.

Written by Cursor Bugbot for commit 7068044. This will update automatically on new commits. Configure here.

…ures

When an address is both a Safe owner AND registered as a delegate/proposer,
the delegate signature restriction was incorrectly applied, preventing
transactions from collecting multiple signatures.

The bug caused "Just one signature is expected if using delegates" error
even when the signer was a legitimate owner who happened to also be in
the delegates list.

The fix checks that the signer is NOT an owner before applying the
delegate restriction. This allows owner-delegates to participate in
normal multi-sig signing flows while still restricting pure delegates
to single signatures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@paulbalaji paulbalaji marked this pull request as ready for review December 2, 2025 14:15
@paulbalaji paulbalaji marked this pull request as draft December 2, 2025 14:18
@paulbalaji paulbalaji marked this pull request as ready for review December 2, 2025 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant