Add fork tests for deposit capacity attack scenarios#299
Open
Add fork tests for deposit capacity attack scenarios#299
Conversation
Five adversarial scenarios covering the deposit capacity system: - Griefing: 10 positions × 1 FLOW minimum exhaust pool capacity (scaled from spec's 1000 × 1 FLOW; mechanically identical, ~50× faster) - Front-running: attacker consumes full capacity ahead of victim; victim's deposit is fully queued with zero collateral credit - Sybil: two accounts each deposit up to the per-position cap, collectively exceeding the limit enforced on a single account - Regeneration monopolization: attacker captures two consecutive regeneration cycles, accumulating 200 FLOW from a 100-token-cap pool - Queued deposit exploitation: queued funds yield no collateral credit, demonstrated by borrow health checks against credited-only balance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #283
Summary
Five adversarial scenarios covering the deposit capacity system:
Deviations from spec
Griefing — 10 positions instead of 1000
The spec calls for 1000 positions each depositing the minimum amount. Each createPosition in fork mode round-trips a mainnet fork node (~3 s). 1000 positions ≈ 50 minutes of test time. The test uses 10 positions × 1 FLOW against depositCapacityCap = 10, which is mechanically identical to 1000 × 1 FLOW against cap = 1000. The attack path through the contract is the same.
Front-running / Griefing — "transaction fails" → deposit queued
The spec says "User A transaction fails due to insufficient capacity." The protocol never reverts an over-capacity deposit — it silently queues the overflow. The tests assert the economic equivalent: victim's funds arrive, transaction succeeds, but the deposit is fully queued with zero immediate collateral credit.
Sybil — combined credit < 2 × perPositionCap
The spec implies each sybil account gets the full per-position allowance. In practice the per-tx deposit limit is depositCapacity × fraction, which erodes with each deposit. After the honest user consumes 100 FLOW, the remaining capacity is 1900, giving sybil1 a per-tx ceiling of 95 (not 100). The test therefore asserts sybilTotalCredit > perPositionCap (the bypass is real) rather than the unreachable == 2 × perPositionCap.
Regeneration monopolization — no "legitimate user starved" assertion
The spec expects a legitimate user to be blocked after the attacker re-deposits. Test.moveTime in fork mode persists across all subsequent blocks, so the legitimate user's transaction would also observe the elapsed time and benefit from another regeneration cycle. The attack is instead proven by the total: two attackers collectively credit 200 FLOW from a 100-token-cap pool across two cycles.
Queued deposit exploitation — race condition not tested
The spec's attack is cancelling queued deposits after manipulating state. The test covers the prerequisite invariant: queued funds do not count as collateral. The race condition itself is not exercisable in a sequential Cadence test environment