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.
View preliminary resultsAppeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.