Skip to content

feat(web): add persistent nonce expiry and replay protection for sign… - #382

Merged
enliven17 merged 2 commits into
enliven17:mainfrom
Abolax123:issue-168-nonce-replay-protection
Jul 27, 2026
Merged

feat(web): add persistent nonce expiry and replay protection for sign…#382
enliven17 merged 2 commits into
enliven17:mainfrom
Abolax123:issue-168-nonce-replay-protection

Conversation

@Abolax123

Copy link
Copy Markdown
Contributor

Summary

Add proposal-based admin timelocks for TalosRegistry and TalosNameService Soroban contracts.

This enforces a configurable minimum delay between scheduling and executing high-impact administrative actions (protocol fee changes, admin transfers, registry pointer updates), giving on-chain observers a guaranteed visibility window before any change takes effect.

Changes

TalosRegistry

  • New types: AdminAction enum (SetProtocolFee, ProposeAdmin), ProposalStatus enum (Scheduled, Executed, Cancelled), TimelockProposal struct, TimelockConfig struct
  • New entry-points: schedule_action, execute_action, cancel_action, set_timelock_config, get_timelock_config, get_timelock_proposal
  • Direct-call guard: set_protocol_fee and propose_admin panic with "Timelock enabled: action must be scheduled" when min_delay > 0
  • New events: tl_sch, tl_exec, tl_cnl, tl_cfg
  • Version bump: CONTRACT_VERSION (1, 0, 0)(1, 1, 0)
  • Backward-compatible default: min_delay = 0 — no behaviour change for existing callers

TalosNameService

  • New types: same AdminAction, ProposalStatus, TimelockProposal, TimelockConfig pattern as Registry
  • New entry-points: schedule_action, execute_action, cancel_action, set_timelock_config, get_timelock_config, get_timelock_proposal
  • New AdminAction variants: SetRegistryContract, SetAdmin
  • Direct-call guard: set_registry_contract and set_admin blocked when min_delay > 0
  • New events: tl_sch, tl_exec, tl_cnl, tl_cfg, reg_upd
  • Version bump: CONTRACT_VERSION (1, 0, 0)(1, 1, 0)
  • Backward-compatible default: min_delay = 0

Documentation

  • contracts/README.md updated with full timelock architecture, entry-points table, auth matrix, event schema, operational runbook (schedule / execute / cancel / rollback CLI examples), known limitations, and version bump notes

Related Issues

Closes #168

Test Plan

  • All existing tests continue to pass
  • New timelock tests added to both contracts:
    • timelock_config_defaults_and_updates — verifies defaults and non-admin guard
    • timelock_schedule_execute_happy_path — full schedule → advance ledger → execute flow
    • timelock_schedule_propose_admin_happy_path — ProposeAdmin action via timelock
    • timelock_early_execution_fails — panics before ETA
    • timelock_expired_execution_fails — panics after grace window
    • timelock_cancellation_clears_proposal — cancel marks Cancelled and blocks re-execution
    • timelock_direct_admin_calls_rejected_when_min_delay_active — direct bypass rejected
    • name_service_timelock_schedule_execute_registry_update — Name Service full flow
    • name_service_timelock_direct_call_guarded — Name Service direct bypass rejected
    • name_service_timelock_cancellation — Name Service cancel flow
  • Automated tests run: cargo test (from contracts/)
  • WASM build verified: cargo build --target wasm32-unknown-unknown --release
  • Manual verification:
    • Confirmed version() returns (1, 1, 0) in both contracts
    • Confirmed get_timelock_config() returns { min_delay: 0, grace_period: 604800 } by default
    • Confirmed direct admin calls succeed when min_delay = 0 (backward-compatible)
    • Confirmed direct admin calls fail when min_delay > 0

Visual Changes

No UI changes.

Checklist

  • I have read the CONTRIBUTING.md guide.
  • My code follows the style guidelines of this project.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings or errors.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • This change is backward-compatible by default (min_delay = 0).

…ed requests

Closes enliven17#168

Replace in-memory Map nonce guard with DB-backed tls_consumed_nonces table.
Consumed nonces are persisted with a UNIQUE constraint on (talosId, nonce)
so single-use semantics hold across process restarts and concurrent requests.
Adds race-condition test with simulated unique-violation concurrency.
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Abolax123 is attempting to deploy a commit to the Cankat's projects Team on Vercel.

A member of the Team first needs to authorize it.

@enliven17
enliven17 merged commit 2b19877 into enliven17:main Jul 27, 2026
@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Abolax123 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security(web): add nonce expiry and replay protection for signed requests

2 participants