MultiSig Timelock

First Flight #55
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Impact: low
Likelihood: high
Invalid

Frontend Displays Proposal Timestamp Instead of Actual Timelock Unlock Time

Root + Impact

Description

Normal behavior

The multisig enforces a timelock on transactions based on ETH value. A transaction may only be executed after its timelock delay has elapsed. Users are expected to rely on the frontend to understand when a transaction becomes executable.

Issue

The frontend stores and displays the transaction’s proposedAt timestamp as the timelock field, rather than computing and displaying the actual unlock time (proposedAt + timelockDelay).

As a result, the UI does not accurately represent whether a transaction is currently executable or still time-locked.

  • Describe the normal behavior in one or more sentences

  • Explain the specific issue or problem in one or more sentences

timelock: proposedAtMs, // @audit: this is proposal time, not unlock time

Likelihood

  • Users commonly rely on the frontend to assess transaction readiness

  • The UI does not currently compute or display remaining timelock duration

  • This affects all delayed transactions

Impact

  • Misleading execution readiness information

  • Increased chance of operator error during sensitive multisig operations

  • Reduced effectiveness of the timelock as a human-safety control

This creates a mismatch between the on-chain execution rules and the information presented to users. Operators may believe a transaction is still locked (or unlocked) based on incorrect UI data, increasing the risk of accidental early or delayed execution.

Proof of Concept

  1. Propose a transaction with an ETH value that triggers a timelock.

  2. Observe that the frontend displays the proposal timestamp.

  3. Compare with on-chain logic: the transaction is only executable at
    proposedAt + calculatedDelay, which is not shown in the UI.

Result: The frontend does not indicate the true unlock time or remaining delay.


Recommended Mitigation

Compute and display the actual unlock timestamp in the frontend.

const delay = getTimelockDelay(tx.value);
const unlockTime = proposedAtMs + delay * 1000;

Additionally:

Display remaining time until execution

Disable or warn on “Execute” until the timelock has expired

Updates

Lead Judging Commences

kelechikizito Lead Judge 4 days ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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

Give us feedback!