The contract implements a strict atomic execution logic in _executeTransaction. If the external interaction fails, the entire transaction is reverted. Consequently, the state update txn.executed = true is rolled back, causing the transaction to remain in a "pending" state executed == false indefinitely. This prevents the transaction from being marked as "failed" and allows for repetitive execution attempts.
Likelihood: Medium
It is highly common for users to propose transactions with incorrect calldata or wrong parameters. Since these transactions never expire, they will stay in the "unexecuted" state forever.
Impact:
There is no direct loss of funds because the revert protects the ETH. However, it causes permanent Gas waste as signers may repeatedly try to execute the "stuck" transaction, and it clutters the contract state with "zombie" entries.
Transferring funds to the EthRejector contract triggers a revert on all incoming payments. The execution fails and the status remains false without being updated. Multiple signers attempting to execute the transaction result in continuous reverts and wasted gas fees.
EthRejector:
place the following code in MultiSigTimelockTest.t.sol:
Eliminate the revert logic by setting executed = true before the external call. If the call fails, emit a TransactionFailed event instead of reverting. this ensures the status is permanently updated on-chain, preventing redundant execution attempts and saving gas for other signers.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.