GivingThanks

First Flight #28
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Invalid

Unsafe low-level call in function `donate()` in `GivingThanks.sol` no checks that the externally called charity address does exist.

Summary

The donate function in GivingThanks.sol performs a low-level .call to transfer funds to charity, without checking whether the address is associated with a deployed contract. According to the Solidity documentation, the EVM considers a low-level call to a non-existing contract to not revert but instead return true, even though the funds may be sent to an invalid address. This can lead to donations being lost or misdirected if the charity address is not properly validated.

Vulnerability Details

Issue

The donate function uses a low-level call to transfer Ether:

(bool sent, ) = charity.call{value: msg.value}("");
require(sent, "Failed to send Ether");

According to the Solidity documentation, when using low-level calls, the EVM does not automatically verify that the target address is associated with a contract. This can lead to silent failures where calls to non-existing contracts succeed even though no code exists at the target address. Normally, Solidity uses extcodesize to ensure the called address has code, but this check is bypassed when using low-level calls. Here, function donate() checks mapping registeredCharities[charity] by calling function isVerified() in CharityRegistry.sol, which does not guarantee the presence of an actual deployed contract.

Solidity Documentation Reference:External Function Calls

In this context, low-level calls bypass this validation, meaning that donations could be sent to non-existing address.

Impact

  • Loss of Funds: If a non-existing contract charity address is used, funds may be sent to an unintended address without error, leading to permanent loss.

Tools Used

  • Solidity documentation and manual code review.

Recommendations

If charity is not an Externally Owned Address implement contract existence checks before transferring funds, use Solidity’s Address.isContract function from the OpenZeppelin library (or a similar method) to verify that the charity address has deployed code.

require(Address.isContract(charity), "Invalid charity address");
Updates

Lead Judging Commences

n0kto Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Appeal created

falde Submitter
12 months ago
n0kto Lead Judge
12 months ago
n0kto Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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