Description:
The contract lacks any mechanism to cancel a proposed transaction. Once a transaction is created via proposeTransaction(), it exists permanently in the contract state and can only be prevented from execution by not gathering enough confirmations or by waiting for the timelock to expire.
However, the timelock only delays execution—it doesn't prevent it. There is no way for signers to formally reject or cancel a malicious or erroneous transaction, even if it gains confirmations. The only defense is for signers to withhold confirmations or revoke them individually, but there's no collective cancellation mechanism.
Impact:
Malicious or erroneous transactions remain in the system indefinitely, creating several risks:
A transaction proposed with wrong parameters cannot be formally cancelled and might accidentally get confirmed and executed later
The transaction ID counter increments forever, potentially leading to gas-intensive iteration over all transactions
The contract state becomes polluted with invalid transactions
If a majority of signers want to reject a transaction, they must coordinate off-chain to ensure it never reaches the threshold, rather than having an on-chain cancellation mechanism
Proof of Concept:
Mitigation:
Add a cancellation mechanism that requires owner approval or a majority of signers:
Alternatively, implement a multi-sig cancellation requiring multiple signers to vote for cancellation.
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.