DatingDapp

AI First Flight #6
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

H-4: 2-of-2 match wallet has no exit, cancel, expiry, or owner rotation

Root + Impact

Matched funds can move only with both approvals, and there is no way to revoke an approval, cancel a transaction, impose an expiry, or replace an owner. A single non-cooperative or key-losing party permanently freezes the shared pot, and a contract owner with no approval entry point can never release it.

Description

// src/MultiSig.sol
function executeTransaction(uint256 _txId) external onlyOwners {
...
@> require(txn.approvedByOwner1 && txn.approvedByOwner2, "Not enough approvals");
@> // no timeout, no cancel, no revoke, no owner rotation
txn.executed = true;
(bool success,) = payable(txn.to).call{value: txn.value}("");
require(success, "Transaction failed");
}

Risk

Likelihood: Medium — a matched user refusing to approve, losing a key, or being a non-callable contract.

Impact: Permanent lock of the matched pair's pooled ETH; no recovery mechanism exists.

Proof of Concept

function test_OneOwnerCanFreezeFunds() public {
address[] memory a = new address[](1);
MultiSigWallet w = new MultiSigWallet(address(this), address(0xBEEF));
vm.deal(address(w), 1 ether);
​
w.submitTransaction(address(0xCAFE), 1 ether);
w.approveTransaction(0); // only owner1 approves
// owner2 never approves -> execute always reverts; no cancel/expiry path
vm.expectRevert(bytes("Not enough approvals"));
w.executeTransaction(0);
}

Recommended Mitigation

+uint256 public constant APPROVAL_EXPIRY = 7 days;
+function cancelTransaction(uint256 _txId) external onlyOwners { ... }
+function revokeApproval(uint256 _txId) external onlyOwners { ... }
+function replaceOwner(address oldOwner, address newOwner) external { ... }
+
function executeTransaction(uint256 _txId) external onlyOwners {
...
+ require(block.timestamp <= txn.createdAt + APPROVAL_EXPIRY, "Expired");
require(txn.approvedByOwner1 && txn.approvedByOwner2, "Not enough approvals");
...
}

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 6 hours 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!