The pool distributes bonus rewards using a K=2 time-weighted formula: amount × (T - entryTime)². The mathematical integrity of this formula strictly dictates an invariant where a user's entry time () must never exceed the terminal resolution time (, stored as riskWindowEnd).
The protocol implementation contains a critical architectural mismatch: riskWindowEnd () is designed as a one-way permanent latch (sealed on the first terminal observation), whereas the deposit gate _assertDepositsAllowed evaluates the bi-directional, live upstream registry state.
Because the DESIGN.md documentation explicitly acknowledges "benign upstream state rewinds" as a valid operational flow, a regression from a terminal state (e.g., PRODUCTION) back to an active-risk state (e.g., UNDER_ATTACK) reopens the stake() function.
Consequently, an attacker can deposit capital while remains permanently frozen in the past. This forces the delta to evaluate as a negative integer. The K=2 formula subsequently squares this negative value, destroying the sign and quadratically inflating the late attacker's score, completely bypassing the intended late-entry penalty.
Likelihood: Medium
The trigger requires the upstream Safe Harbor Registry to undergo a state rewind after a terminal state has been locally observed by the pool.
While the upstream Registry is managed by a trusted DAO, this finding does not rely on a malicious admin. The DESIGN.md explicitly documents that "A benign upstream state rewind cannot re-open withdraw: that is gated on the one-way riskWindowStart..." The developers correctly architected a one-way local latch to protect withdrawals from upstream rewinds, but completely failed to implement the corresponding one-way latch to protect the deposit math invariant (). Relying on an external operational flow to implicitly protect an internal mathematical boundary is a systemic design flaw, not an accepted admin risk.
Impact: High
Direct Theft of Yield via Math Exploitation: An attacker successfully hijackings the squared negative time delta mathematically steals the vast majority of the bonus pool. In the provided PoC, the attacker captures ~90% of the yield despite matching the legitimate user's capital, completely destroying the economic model of the Confidence Pool.
Dilution of Legitimate Risk Capital: Legitimate early stakers suffer near-total financial dilution, having their rightful risk-premium hijacked by users entering after the risk window had technically concluded.
Place the test inside the test/fork/ folder
run the test with forge test --match-test test_UpstreamRewind_QuadraticInflationExploit -vvv --fork-url https://testnet.battlechain.com
Note: the test uses
vm.mockCallto imitate the required state (hence the Likelihood is Medium) and does not tinker/changes anything else.
The current architecture protects withdraw() from upstream rewinds using a local one-way latch (riskWindowStart != 0), but fails to protect stake().
The mitigation implements the exact same architectural pattern for deposits using the terminal latch (riskWindowEnd != 0). Rather than attempting to restrict the DAO's upstream operational flows (which validly include state rewinds), this check isolates the pool's internal math. It acts as an absolute execution guardrail for the K=2 curve, guaranteeing that no new entry time () can be recorded after the terminal time () is permanently sealed. This decisively prevents the negative time-delta underflow and mathematically eliminates the quadratic inflation vector with minimal gas overhead.
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.