Vanguard

First Flight #56
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Cross-Operation State Desynchronization Allows Privileged Action Execution Without Required Quorum

Root + Impact

Description

  • The multisig system is designed to ensure that each sensitive operation reaches the required confirmation threshold before it becomes executable.

However, confirmation tracking is not scoped to the full operation lifecycle, allowing confirmations obtained under one governance state to be reused after critical state changes, leading to execution of privileged actions without satisfying the intended quorum under the final state.

// @> Confirmations are tracked independently of operation-critical state
confirmTransaction(txId);
...
updateRequirement(newRequiredConfirmations);
...
executeTransaction(txId); // executes using stale confirmation set

Risk

Likelihood:

  • Occurs during normal governance flows where signer set or confirmation thresholds are modified

Common when protocol performs upgrades, signer rotations, or security responses

Impact:

  • Allows execution of high-privilege transactions with fewer confirmations than intended

Breaks the core multisig invariant: “execution reflects current governance requirements”

Proof of Concept

  • The transaction’s confirmation set is not invalidated or re-evaluated after the confirmation requirement changes. This causes a time-of-check vs time-of-use mismatch, where the transaction passes checks that no longer reflect governance reality.

// Initial state: required confirmations = 2
submitTransaction(target, value, data); // txId = X
confirmTransaction(X); // signer A
confirmTransaction(X); // signer B (X now executable)
// Governance change
submitTransaction(
address(this),
0,
abi.encodeWithSelector(updateRequirement.selector, 3)
);
executeTransaction(updateTxId);
// Now required confirmations = 3
// But tx X still has 2 confirmations recorded
executeTransaction(X); // executes despite insufficient quorum

Recommended Mitigation

  • Invalidate or rebind confirmations whenever governance-critical parameters change.

- remove this code
+ add this code
function updateRequirement(uint256 newRequirement) external onlyGovernance {
+ _invalidateAllPendingTransactions();
requiredConfirmations = newRequirement;
}
function executeTransaction(uint256 txId) external {
- require(isConfirmed(txId), "Not enough confirmations");
+ require(
+ isConfirmedUnderCurrentRequirement(txId),
+ "Confirmations invalid under current governance"
+ );
}
Updates

Appeal created

chaossr Lead Judge 17 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!