Expected behavior: Any refund to a user is performed safely; if direct transfer fails, the contract should handle it (e.g., by crediting a withdrawable balance).
Actual behavior: send(msg.sender, excess) is called but its return is ignored — if send fails, the refund silently fails and funds remain stuck in the contract (or user loses expected refund).
send in Vyper returns bool but does not revert on failure. Not checking its result means refunds might fail quietly (e.g., if the recipient is a contract using >2300 gas or if gas stipend is insufficient).
Likelihood
Medium — send failures occur when the recipient is a contract with non-trivial fallback or gas requirements.
Impact
1.Users may permanently lose expected refunds.
2.Funds can become trapped inside CustomerEngine and distort accounting.
3.A malicious user contract could lead to repeated failed refunds and eventual fund misallocation.
A tiny Solidity attacker contract that forces refunds to fail by reverting in its fallback (so send from CustomerEngine.vy returns false and the refund is lost).
Use a pull-refund pattern or check send return and fallback to credit:
Vyper’s send() reverts on failure, so refund attempts to contract wallets with complex fallback logic can halt trigger_demand() entirely. This causes a denial-of-service for affected users but does not result in fund loss.
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.