DatingDapp

First Flight #33
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Multisig Transaction May Fail Due to Invalid Recipient Address - MultiSigWallet.sol

Summary

Vulnerability Details

  1. Insufficient Recipient Validation:

    function submitTransaction(address _to, uint256 _value) external onlyOwners {
    // No check if _to can receive ETH
    payable(txn.to).call{value: txn.value}("");
    }

    The submitTransaction function does not validate if the recipient address has a valid receive or fallback function, allowing transactions to be submitted that are guaranteed to fail.

  2. Permanent Transaction Termination on Failure:
    If _to is a contract without a receive or fallback function, the .call in executeTransaction will revert, but the transaction is still marked as executed (though the state change is rolled back due to the require(success) statement). However, users may incorrectly assume the transaction failed without understanding the funds remain trapped.

Impact

  • Funds Lock-Up: Users may inadvertently submit transactions to non-reolvable addresses, causing funds to be stuck in the multisig wallet.

  • User Confusion: Failed transactions are not clearly communicated, leading to frustration and loss of trust.

Tools Used

  • Slither for static analysis (identified unchecked external calls).

Recommendations

  1. Validate Recipient Capabilities:
    Implement a check in submitTransaction to ensure the _to address has a valid receive or fallback function.

    function canReceive(address _addr) internal view returns (bool) {
    // Check via EXTCODESIZE (non-contract addresses have 0)
    if (_addr.code.length == 0) {
    return true; // EOAs can receive ETH
    }
    // Check for receive/fallback function
    bytes memory callData = abi.encodeWithSignature("receive()");
    (bool success,) = _addr.staticcall(callData);
    return success;
    }
  2. Revert Invalid Transactions Early:
    Modify submitTransaction to revert if the recipient is invalid.

    function submitTransaction(address _to, uint256 _value) external onlyOwners {
    require(_to != address(0), "Invalid recipient");
    require(_value > 0, "Invalid amount");
    require(canReceive(_to), "Recipient cannot receive ETH");
    transactions.push(Transaction(...));
    emit TransactionCreated(...);
    }
  3. Include Error Handling:
    Update the executeTransaction error message to specify the transaction failed due to an invalid recipient.

    if (!success) {
    revert TransactionFailed("Recipient rejected ETH transfer");
    }

Fixed Code Snippet:

By validating recipients and reverting invalid transactions, the multisig contract ensures safer fund management and clearer user feedback.

function executeTransaction(uint256 _txId) external onlyOwners {
require(_txId < transactions.length, "Invalid transaction ID");
Transaction storage txn = transactions[_txId];
require(!txn.executed, "Transaction already executed");
require(txn.approvedByOwner1 && txn.approvedByOwner2, "Not enough approvals");
txn.executed = true;
(bool success,) = payable(txn.to).call{value: txn.value}("");
if (!success) {
revert TransactionFailed("ETH transfer failed");
}
emit TransactionExecuted(_txId, txn.to, txn.value);
}
Updates

Appeal created

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Users mistake, only impacting themselves.

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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