GivingThanks

First Flight #28
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

[H-01] `GivingThanks::registry` is initialised with the incorrect address in the `GivingThanks` constructor

Summary

The registry state variable in the GivingThanks contract is initialised with the address of the msg.sender, as opposed to the constructor parameter _registry.

Vulnerability Details

The function GivingThanks::donate relies on the registry::isVerified function to verify that the charity parameter is a whitelisted charity.

function donate(address charity) public payable {
@> require(registry.isVerified(charity), "Charity not verified");
(bool sent,) = charity.call{value: msg.value}("");
require(sent, "Failed to send Ether");
...
}

However, as the registry was initialised with the address of owner as opposed to the correct contract address, the call to the GivingThanks::donate function will revert.

constructor(address _registry) ERC721("DonationReceipt", "DRC") {
@> registry = CharityRegistry(msg.sender);
owner = msg.sender;
tokenCounter = 0;
}

Impact

It is impossible for donors to donate to a charity, as the GivingThanks::donate function will always revert on the first require check.

Proof of Code

Run the following command:

forge test -vvvv --mt testDonate

Output:

Ran 1 test for test/GivingThanks.t.sol:GivingThanksTest
[FAIL. Reason: EvmError: Revert] testDonate() (gas: 27751)
Traces:
[1851260] GivingThanksTest::setUp()
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← [Return] admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF]
├─ [0] VM::label(admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF], "admin")
│ └─ ← [Return]
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← [Return] charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A]
├─ [0] VM::label(charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A], "charity")
│ └─ ← [Return]
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← [Return] donor: [0xBd4D11D884c3c7bF373b013AC52fd99f9DD86D0A]
├─ [0] VM::label(donor: [0xBd4D11D884c3c7bF373b013AC52fd99f9DD86D0A], "donor")
│ └─ ← [Return]
├─ [0] VM::prank(admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF])
│ └─ ← [Return]
├─ [191749] → new CharityRegistry@0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395
│ └─ ← [Return] 847 bytes of code
├─ [0] VM::prank(admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF])
│ └─ ← [Return]
├─ [1443803] → new GivingThanks@0x6D9da78B6A5BEdcA287AA5d49613bA36b90c15C4
│ └─ ← [Return] 6753 bytes of code
├─ [0] VM::prank(admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF])
│ └─ ← [Return]
├─ [22464] CharityRegistry::registerCharity(charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A])
│ └─ ← [Stop]
├─ [0] VM::prank(admin: [0xaA10a84CE7d9AE517a52c6d5cA153b369Af99ecF])
│ └─ ← [Return]
├─ [22860] CharityRegistry::verifyCharity(charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A])
│ └─ ← [Stop]
└─ ← [Stop]
[27751] GivingThanksTest::testDonate()
├─ [2383] GivingThanks::tokenCounter() [staticcall]
│ └─ ← [Return] 0
├─ [0] VM::deal(donor: [0xBd4D11D884c3c7bF373b013AC52fd99f9DD86D0A], 10000000000000000000 [1e19])
│ └─ ← [Return]
├─ [0] VM::prank(donor: [0xBd4D11D884c3c7bF373b013AC52fd99f9DD86D0A])
│ └─ ← [Return]
├─ [5256] GivingThanks::donate{value: 1000000000000000000}(charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A])
│ ├─ [0] admin::isVerified(charity: [0x59cf1Fbe6AD1EBf1a01e78EE808B7c889E6dd58A]) [staticcall]
│ │ └─ ← [Stop]
│ └─ ← [Revert] EvmError: Revert
└─ ← [Revert] EvmError: Revert

As can be seen, the test failed due to the function call to CharityRegistry::isVerified reverting, as the CharityRegistry contract was initialised with the wrong address.

Tools Used

Manual review & foundry unit tests

Recommended Mitigation

Use the parameter _registry instead of the msg.sender to initialise the CharityRegistry contract for the state variable registry.

constructor(address _registry) ERC721("DonationReceipt", "DRC") {
+ registry = CharityRegistry(_registry);
- registry = CharityRegistry(msg.sender);
owner = msg.sender;
tokenCounter = 0;
}
Updates

Lead Judging Commences

n0kto Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-bad-registry-set-at-construction

Likelyhood: High, the parameter is not well used and won't be set. Impact: Low, can be changed with the setter and no one will be able to donate to malicious charity.

Support

FAQs

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