Verifying Multisig Transactions
The security of a multisig wallet relies on each signer independently verifying what they are signing. A compromised web interface could present a legitimate-looking transaction while tricking a hardware wallet into signing a malicious one.
The verification process is divided into two distinct phases: signing the off-chain message and executing the on-chain transaction.
Key Definitions (EVM)
- Domain Hash: EIP-712 domain separator, unique to each Safe. Ensures signatures cannot be replayed on other networks or Safes.
- Message Hash: Raw hash of transaction parameters. This appears on your hardware wallet.
- SafeTxHash: Combined hash of domain + message hash. Used for nested Safe approvals.
Phase 1: Signing the Off-Chain Message
When you are the first signer or are adding your signature to a transaction that has not yet met its threshold, you are not sending an on-chain transaction. Instead, you are signing a structured, off-chain message that conforms to the EIP-712 standard.
Goal: To confirm that the cryptographic hash displayed on your hardware wallet exactly matches the hash of the transaction you intend to approve.
Process
- Initiate Signing: Start the signing process in the multisig wallet's web interface.
- Verify on Hardware Wallet: Your hardware wallet will display an EIP-712 hash for you to sign.
- Compute Hash: Use an independent, local tool to re-calculate the expected hash from the transaction's parameters (
nonce,to,value,data, etc.). For a list of recommended options, see the Transaction Verification Tools section. - Compare Hashes: Compare the
SafeTxHashgenerated by the local tool with the hash displayed on your hardware wallet's screen. They must match perfectly. - Sign: If the hashes match, you can confidently sign the message on your hardware wallet. This confirms you are approving the correct transaction, even if the web UI has been compromised.
Phase 2: Executing the On-Chain Transaction
Once a transaction has the required M-of-N signatures, it can be executed. This involves submitting a final on-chain transaction that calls the execTransaction function on the multisig contract, passing in all the previously signed data.
Goal: To confirm that the on-chain transaction being sent correctly encapsulates the multisig transaction you and other signers approved.
Process
- Initiate Execution: In the multisig interface, start the execution of the fully signed transaction.
- Verify Calldata: Your hardware wallet will prompt you to sign a new on-chain transaction. It will display the raw transaction data (calldata), which should show a call to the
execTransactionfunction. - Decode and Compare: Use a calldata decoder (e.g.,calldata.swiss-knife.xyz) to parse the data shown on your hardware wallet.
- Confirm Parameters: Carefully check the decoded parameters within the
execTransactioncall, especially the internal destination address (to),value, anddatapayload. Ensure they match the original, intended transaction. - Sign and Broadcast: If the calldata is correct, sign the transaction on your hardware wallet to broadcast it to the network.
Operational Best Practices
⚠️ Beware of
DELEGATECALL: In a smart contract multisig transaction, anoperation: 1 (DELEGATECALL)is dangerous if the target contract is not explicitly known and trusted. This opcode gives another contract full control over your wallet's context and storage.
- Transaction Simulation: Before signing, use a simulator like Tenderly or Alchemy to preview the transaction's outcome. This helps confirm that it will not revert and will result in the expected state changes.
- Hardware Wallet Standard: All multisig signers should use hardware wallets to protect their keys from online threats. Data shown in a browser extension wallet should be treated with the same skepticism as data in the web UI.
- Secure signing environment: Use a dedicated, air-gapped, or hardened device. Avoid primary work laptops.
- Alternative Frontends: To further reduce reliance on a single public UI, consider using an alternative or self-hosted multisig interface.
- Separate browser/profile for signing: Use a dedicated browser or browser profile when interacting with signing UIs to reduce cross-extension/session risk.
- Require a "how to check" guide: Every transaction should include explicit verification instructions for signers.
- Verify addresses and amounts via independent sources: Do not rely solely on messages from co-signers.
- Check transactions in the queue: If unclear what a transaction does and why, do not sign; ask for explanation.
- Communicate status: After review, state whether a transaction is ready to execute and confirm after signing ("checked, signed, X more required").
- Last signer executes: If executable immediately, the last signer should execute; otherwise coordinate clearly.
- Re-verify before execution: Treat execution as a fresh signing event and re-check parameters.
- Use checksummed addresses: Always use checksummed format to prevent copy/paste or case errors.
Simulation notes with timelocks
When using a timelock, simulations may show the staging event rather than actual execution. Inspect the staged payload and verify cancellation/execution roles and parameters before proceeding.