fund() enforces that only the owner can add ETH to the contract. The receive() fallback, which handles plain ETH transfers, has no equivalent check and accepts ETH from any address.
Likelihood:
Any address can send ETH directly to the contract at any time; no privileged access is required.
A griefing actor has no financial incentive, so this is less likely to be exploited maliciously than other findings.
Impact:
Breaks the owner-only funding invariant; off-chain systems relying on Funded events to track authorized funding will record unauthorized entries.
An actor can keep the balance permanently above zero, interfering with any zero-balance logic or monitoring that assumes only the owner adds funds.
Any external account can send ETH directly to the contract's address using a plain transfer, bypassing the ONLY_OWNER_CAN_FUND guard entirely. The receive() fallback accepts the value unconditionally and emits a Funded event, making the unauthorized deposit indistinguishable from an owner-initiated one in off-chain monitoring systems.
Adding a sender check inside receive() enforces the same invariant already expressed in fund(), ensuring that the Funded event is only ever emitted for authorized deposits. Alternatively, removing receive() altogether and directing all ETH intake through fund() eliminates the discrepancy at the cost of requiring callers to use the explicit function signature rather than plain transfers.
Or remove receive() entirely and rely solely on fund().
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.