stake sets the one-way expiryLocked latch on its first call, permanently preventing the sponsor from calling setExpiry. Per docs/DESIGN.md §10 this protects staker reliance on expiry, which feeds the k=2 bonus formula as T on the EXPIRED path. contributeBonus accepts funds through the same _assertDepositsAllowed gate but does not set expiryLocked. As a result, while no stake has yet occurred, the sponsor can accept a bonus contribution and then freely extend or shorten expiry (down to the _MIN_EXPIRY_LEAD floor), changing how long the contributed funds are exposed and when the pool can resolve.
The latch's DESIGN rationale is framed entirely around the staker's T-weighting; contributors hold no T-position, so the protection was never extended to them. §10 does not state this asymmetry is intentional.
Likelihood: Low — requires a bonus-before-stake ordering and a sponsor motivated to reprice the timeline.
Impact: Low — no principal theft. The sponsor already holds strictly larger levers over bonus funds (pause on the deposit paths, bad-faith CORRUPTED sweep to their own recovery address). This is pure timeline manipulation of already-committed contributor funds.
An independent user contributes bonus first. The sponsor then changes the pool's expiry. This would not be possible if a staker had deposited first.
Mirror stake's latch, or document the asymmetry in DESIGN §10 the way §5/§9 close off other recurring false positives.
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.