The submitTransaction function allows either owner to propose a transaction with any _value, including values greater than the wallet's current balance. The executeTransaction function only checks that both owners have approved the transaction — it does not validate that address(this).balance >= txn.value before calling payable(txn.to).call{value: txn.value}.
If the _value exceeds the contract's balance, the low-level call will fail and the require(success) will revert. However, the transaction remains in the transactions array with executed = false. If both owners have already approved it, they cannot revoke their approvals (there is no revoke function), so the only option is to submit a new transaction.
More critically, a malicious co-owner can grief by continuously submitting transactions with inflated values that will always fail on execution. Since there is no mechanism to cancel or remove transactions, and no way to withdraw funds except through the multisig approval process, a single malicious owner can effectively block the other owner from accessing any funds.
Likelihood:
This occurs whenever a transaction is submitted with a value exceeding the contract's balance, either by mistake or maliciously.
A malicious co-owner (matched user who turns adversarial) has direct incentive to grief the other party.
Impact:
Funds can be permanently locked if a malicious co-owner refuses to cooperate on valid transactions.
There is no mechanism to cancel pending transactions or revoke approvals, compounding the griefing attack.
This test deploys a MultiSig with 1 ETH, then Bob submits a transaction for 100 ETH. Both owners approve, but execution reverts due to insufficient balance. The transaction is now stuck — both approvals are consumed, there is no revoke function, and Alice's funds are locked unless Bob cooperates on a new transaction.
Add a balance check in executeTransaction for a clearer error, and implement a mechanism to cancel or revoke transactions. This prevents permanently stuck state and griefing.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.