Skip to content

feat(registry): memo validation at registration time (type + length checks)Β #9

Open

Description

@Meet-hybrid

πŸ’  Sidera β€” Stellar Name Service. Contribute via Drips Wave / GrantFox. Comment with your approach and wait for assignment before starting.

Description

The registry stores the memo hint as an opaque string. But Stellar memos have hard protocol constraints β€” MEMO_ID is a u64, MEMO_TEXT is ≀ 28 bytes β€” and a hint that violates them produces a registration that LOOKS helpful but builds un-sendable payments. The SDK's parser currently truncates defensively; the contract should reject garbage at the source instead.

Desired outcome: register and set_address validate the memo hint β€” pure digits (a valid u64) become a typed ID memo; otherwise text ≀ 28 bytes β€” and reject anything else with a descriptive error.

Scope

  • Crate/module: crates/registry, src/lib.rs
  • API: no signature changes; Resolution.memo stays Option<String> (rendering as ID vs text is a client concern); a shared validate_memo helper is added
  • Storage: none
  • Tests: valid ID memos (u64 boundaries 0, u64::MAX); valid text memos (1, 28-byte boundaries incl. multibyte UTF-8); over-long text rejected; digits exceeding u64 rejected; empty-string memo normalized to None; set_address path covered identically
  • Docs: memo rules section (mirror the SDK's parseMemoHint contract)

Non-goals

  • Storing typed memo enums on-chain (rendering stays client-side β€” document why)
  • SDK-side changes (the SDK parser already handles legacy/foreign data)
  • Migrating already-registered names (the deployed instance has one test name; state the clean-cutover assumption)

What "done" looks like

  • New RegistryError::InvalidMemo at the next free code, with doc comment
  • register with memo "18446744073709551616" (u64::MAX+1) β†’ InvalidMemo
  • register with a 29-byte text memo β†’ InvalidMemo; exactly 28 bytes (multibyte-safe) accepted
  • Empty/whitespace memo string stored as None
  • set_address enforces identical rules (shared helper)
  • Property-style test isn't required β€” a boundary matrix is enough
  • All gates pass

Implementation guidelines

  • Byte-length via the string's bytes iterator (no std; String::len() gives bytes in Soroban env strings)
  • u64 validation without allocation: length ≀ 20 chars AND parseable β€” careful with leading zeros (allow them: exchange convention β€” but they must still parse as u64; document that "000123" is accepted and treated as ID)
  • Keep validation BEFORE require_auth so bad calls fail cheap (existing house ordering for input validation)
  • Mirror the SDK's parseMemoHint rules exactly so client and contract can never disagree

Verification

cargo fmt --all -- --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test -p sidera-registry --all-targets --locked

PR guidelines

  • Get assigned before starting; do not start work on a reserved issue.
  • Work in a fork; branch off upstream/main; open the PR against Sidera-Protocol/sidera-contracts:main.
  • PR description must include Closes #9.
  • All CI checks must pass; human maintainer review required.

Metadata

  • Affected crates/files: contracts/registry/src/lib.rs
  • Complexity label: complexity: medium (150 base points)
  • Type labels: enhancement

Activity

  1. Rodrigoue9 commented on Oct 7, 2026

    @Rodrigoue9

    Hi @maintainer! I would like to implement the memo validation logic for the registry.

    Technical Outline:

    1. Validation Rules (validate_memo helper):
      • Check byte-length using env string bytes iterator (no std allocation).
      • If numeric: validate that it parses cleanly as u64 (supporting leading zeros up to 20 digits, matching exchange conventions). Rejects > u64::MAX.
      • If text: enforce bytes.len() <= 28 (multibyte UTF-8 safe). Rejects 29+ bytes.
      • Empty/whitespace memo normalized to None.
    2. Execution Timing:
      • Execute validate_memo BEFORE require_auth in both register and set_address so invalid calls fail fast and cheap.
      • Introduce RegistryError::InvalidMemo with explicit documentation.
    3. Test Matrix:
      • Boundary checks for u64::MAX, u64::MAX + 1, 28-byte strings, 29-byte strings, multi-byte UTF-8 characters, and whitespace.
    4. Verification:
      • Full workspace test pass and zero clippy warnings.

    Track Record

    Looking forward to your assignment!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    complexity: mediumStandard features or involved bug fixes (150 pts)enhancementNew feature or requestexternal-contributorsSuitable for contributors outside the maintainer team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions