Summary
register (contracts/tholos-v2/src/lib.rs:1180-1261) requires a deposit to meet policy.min_resolution_bond only when creating a brand-new position (lib.rs:1246-1249, the None branch of matching against an existing position). A top-up on an existing position has no minimum at all, previous_amount is read from the existing position and new_amount = previous_amount + amount accepts any amount > 0, including 1 unit of the smallest token denomination.
Separately, every register call unconditionally re-checks the anti-snipe extension condition (lib.rs:1225-1231):
if now >= resolution.registration_deadline.saturating_sub(assertion.policy.anti_snipe_extension_secs) {
let extended = now + assertion.policy.anti_snipe_extension_secs;
resolution.registration_deadline = extended.min(resolution.registration_hard_deadline);
}
Once an address has an existing position, it can call register repeatedly with a 1-unit top-up each time it lands inside the extension window, re-triggering the extension on every call, capped only by registration_hard_deadline. This lets a single low-cost actor unilaterally prolong registration up to the full hard maximum, regardless of whether a real last-moment deposit is actually happening, a griefing/delay vector against anyone trying to reach Reveal promptly.
Scope
- Require top-up deposits to also meet some minimum (either
min_resolution_bond itself, or a separate, smaller anti-snipe-qualifying minimum), so a 1-unit deposit can't unilaterally extend the deadline.
- Alternative or additional mitigation: rate-limit or cap how many times a single address's top-ups can trigger an extension within one registration period.
- Add a test demonstrating that a sequence of minimal top-ups from one address can currently push
registration_deadline to registration_hard_deadline, and that the fix closes it.
Proposed approach
The simplest fix is extending the existing minimum-bond check to top-ups, not just new positions: require amount >= some_minimum (open question for the assignee: reuse min_resolution_bond directly, or introduce a smaller anti-snipe-specific floor) regardless of whether the position already exists, so a deposit has to be large enough to plausibly represent a real change in position, not a griefing-sized dust top-up.
Summary
register(contracts/tholos-v2/src/lib.rs:1180-1261) requires a deposit to meetpolicy.min_resolution_bondonly when creating a brand-new position (lib.rs:1246-1249, theNonebranch of matching against an existing position). A top-up on an existing position has no minimum at all,previous_amountis read from the existing position andnew_amount = previous_amount + amountaccepts anyamount > 0, including 1 unit of the smallest token denomination.Separately, every
registercall unconditionally re-checks the anti-snipe extension condition (lib.rs:1225-1231):Once an address has an existing position, it can call
registerrepeatedly with a 1-unit top-up each time it lands inside the extension window, re-triggering the extension on every call, capped only byregistration_hard_deadline. This lets a single low-cost actor unilaterally prolong registration up to the full hard maximum, regardless of whether a real last-moment deposit is actually happening, a griefing/delay vector against anyone trying to reachRevealpromptly.Scope
min_resolution_bonditself, or a separate, smaller anti-snipe-qualifying minimum), so a 1-unit deposit can't unilaterally extend the deadline.registration_deadlinetoregistration_hard_deadline, and that the fix closes it.Proposed approach
The simplest fix is extending the existing minimum-bond check to top-ups, not just new positions: require
amount >= some_minimum(open question for the assignee: reusemin_resolution_bonddirectly, or introduce a smaller anti-snipe-specific floor) regardless of whether the position already exists, so a deposit has to be large enough to plausibly represent a real change in position, not a griefing-sized dust top-up.