stake() computes received via balance-diff as defense-in-depth against fee-on-transfer:
There is no ceiling check. When a rebase inflates the pool's balance between the two calls, received > amount. Walkthrough:
Pool holds 1000 tokens. Token rebases +5% → balance silently becomes 1050.
Attacker calls stake(100). balanceBefore=1050, transfer 100, balanceAfter=1150.
received = 150. Attacker credited 150 instead of 100. The 50 extra was the pool's pre-existing rebase gain.
The balance-diff handles received < amount (FOT) but over-credits on received > amount (rebase). The Factory allowlists only at creation time (L77); de-listing doesn't affect existing pools. The test suite only covers FOT (ConfidencePool.fot.t.sol), with no test for received > amount. docs/DESIGN.md does not document this behavior.
While the precondition (proxy-upgrade token → rebase) is specific, the impact is direct fund loss, not a theoretical edge case. The pool accounting breaks permanently: totalEligibleStake diverges from actual token balance and cannot self-correct. Affected pools remain exploitable until resolution. The same vector in contributeBonus() inflates totalBonus, amplifying the bonus dilution.
The PoC simulates a proxy-upgraded token where balanceOf returns an ever-increasing value after a rebase event. Alice stakes legitimately, a rebase triggers, then Bob stakes during the rebase window. Bob is credited more than he transferred, and total tracked stake exceeds actual pool balance.
Add a ceiling check after computing received in both stake() and contributeBonus():
This preserves the FOT defense while preventing rebase inflation.
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.