Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion allways/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

# ─── Reservation ─────────────────────────────────────────
RESERVE_SLIPPAGE_DEFAULT_BPS = 200 # 2% — applied when the synapse omits slippage
RESERVE_SLIPPAGE_MAX_BPS = 100_000 # 1000% — clamp ceiling (mostly an integer/typo guard)
RESERVE_SLIPPAGE_MAX_BPS = 2_500 # 25% — clamp ceiling; ≥10_000 turns the rate gate into a no-op
RESERVATION_COOLDOWN_BLOCKS = 150 # ~30 min base cooldown on failed reservation
RESERVATION_COOLDOWN_MULTIPLIER = 2 # 150 → 300 → 600 ...
MAX_RESERVATIONS_PER_ADDRESS = 1
Expand Down
1 change: 1 addition & 0 deletions allways/validator/axon_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ async def handle_swap_reserve(
bt.logging.info(
f'{ctx}: REQUEST received — tao={synapse.tao_amount} '
f'from_amount={synapse.from_amount} to_amount={synapse.to_amount} '
f'slippage_bps={synapse.slippage_bps} '
f'user_from_address={synapse.from_address} block_anchor={synapse.block_anchor}'
)

Expand Down
22 changes: 14 additions & 8 deletions tests/test_axon_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,25 +694,31 @@ def test_wider_user_slippage_accepts_large_drift(self):
assert result.accepted is True

def test_slippage_max_bps_clamp_applied(self):
"""slippage_bps above RESERVE_SLIPPAGE_MAX_BPS is clamped, not errored.

With the clamp applied, even a very large drift (rate dropped 90%)
passes the slippage gate because MAX_BPS >= 10_000 makes the threshold
non-positive.
"""slippage_bps above RESERVE_SLIPPAGE_MAX_BPS is clamped, not errored,
and the cap is tight enough to still gate a wildly-off quote.

MAX_BPS must stay below 10_000 (100%) — at ≥10_000 the threshold goes
non-positive and the gate becomes a no-op, which is what let swap-550's
operator-test traffic settle a 71%-off quote without rejection. The
clamp should accept the high request value but cap it to a band that
still bites real misquotes.
"""
from allways.constants import RESERVE_SLIPPAGE_MAX_BPS

assert RESERVE_SLIPPAGE_MAX_BPS < 10_000, 'cap ≥10_000 makes quote_within_slippage a no-op — see swap 550'

validator = make_reserve_validator()
# Rate dropped 90% → recomputed = 10% of 345_000_000 = 34_500_000.
# Default 2% band would reject this, but MAX_BPS uncaps it.
# With the cap at 25% (or anything <90%), this gap is still rejected
# even after the user-requested slippage gets clamped down.
moved = make_commitment()
moved.rate_str = str(345 * 0.10)
moved.rate = 345 * 0.10
synapse = make_reserve_synapse()
synapse.slippage_bps = RESERVE_SLIPPAGE_MAX_BPS + 1_000_000 # absurdly large — clamped
result = run_reserve_handler(validator, synapse, commitment=moved)
# With MAX_BPS applied, gate passes; default 2% would reject
assert result.accepted is True
assert result.accepted is False
assert 'slippage band' in result.rejection_reason

# ------------------------------------------------------------------ #
# tao_amount internal consistency #
Expand Down