MultiSig Timelock

First Flight #55
Beginner FriendlyWallet
100 EXP
Submission Details
Impact: medium
Likelihood: medium

Transaction Identity Collision Due to Missing Nonce Domain Separation

Author Revealed upon completion

Root + Impact

Description

  • Each multisig transaction must be uniquely identifiable, even when calldata and targets are reused, so that signer confirmations apply only to the intended action.

  • Transaction identity is derived without a nonce or domain separator, allowing multiple transactions with identical (target, value, data) to share the same hash.

// @> Missing nonce in transaction identity
bytes32 txHash = keccak256(abi.encode(target, value, data));
// This causes confirmation ambiguity across transactions.

Risk

Likelihood:

  • Governance frequently reuses calldata (e.g., repeated transfer() calls).

Treasury operations often repeat the same actions over time.

Impact:

  • Confirmations may unintentionally apply to later transactions.

Signer intent is violated, weakening multisig trust guarantees.

Proof of Concept

  • Without a nonce, the contract cannot distinguish between logically separate actions that look identical at the calldata level.

// Tx A
submitTransaction(target, 0, data);
// Tx B (same calldata)
submitTransaction(target, 0, data);
// Both share identical hash → confirmations overlap

Recommended Mitigation

  • Guarantees transaction uniqueness.

Prevents replay or confirmation reuse.

  • Matches industry-standard multisig designs (Gnosis Safe–style domain separation).

- remove this code
+ add this code
- bytes32 txHash = keccak256(abi.encode(target, value, data));
+ bytes32 txHash = keccak256(
+ abi.encode(txId, target, value, data)
+ );

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!