SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
Submission Details
Impact: low
Likelihood: high

(LOW) `receive()` is public and unrestricted, completely bypassing the `OnlyOwnerCanFund` check on `fund()`

Author Revealed upon completion

Location: contracts/src/TreasureHunt.sol:236-241 (fund) vs contracts/src/TreasureHunt.sol:287-289 (receive)

Description

fund() is owner-only:

function fund() external payable {
require(msg.sender==owner, "ONLY_OWNER_CAN_FUND");
require(msg.value > 0, "NO_ETH_SENT");
emit Funded(msg.value, address(this).balance);
}

But receive() accepts ETH from anyone and emits the same Funded event:

receive() external payable {
emit Funded(msg.value, address(this).balance);
}

A non-owner can send ETH directly to the contract address, deposit any amount, and trigger a Funded event bypassing the ONLY_OWNER_CAN_FUND restriction.

Risk

Likelihood: High. Very easy to transfer ETH directly.

Impact: Low. No one can steal but anyone can send ETH to the contract.

Proof of Concept

function test_ReceiveBypassesOnlyOwnerFund() public {
address stranger = makeAddr("stranger");
vm.deal(stranger, 5 ether);
// fund() requires owner:
vm.prank(stranger);
vm.expectRevert("ONLY_OWNER_CAN_FUND");
hunt.fund{value: 1 ether}();
// But receive() does not:
uint256 balBefore = address(hunt).balance;
vm.prank(stranger);
(bool ok, ) = address(hunt).call{value: 1 ether}("");
assertTrue(ok);
assertEq(address(hunt).balance, balBefore + 1 ether);
}

Run:

forge test --match-test test_ReceiveBypassesOnlyOwnerFund -vv

The test passes stranger's fund() call reverts, but their direct ETH transfer succeeds.

Recommended Mitigation

Either restrict receive() with the same owner check, or delete it entirely and force all deposits through fund().

receive() external payable {
+ require(msg.sender == owner, "ONLY_OWNER_CAN_FUND");
emit Funded(msg.value, address(this).balance);
}

Or:

- receive() external payable {
- emit Funded(msg.value, address(this).balance);
- }

Support

FAQs

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

Give us feedback!