Skip to content

feat(contracts): scaffold Soroban smart contracts workspace#235

Merged
Petah1 merged 4 commits into
scout-off:mainfrom
pitah23:feat/soroban-contracts-scaffold
Jun 20, 2026
Merged

feat(contracts): scaffold Soroban smart contracts workspace#235
Petah1 merged 4 commits into
scout-off:mainfrom
pitah23:feat/soroban-contracts-scaffold

Conversation

@pitah23

@pitah23 pitah23 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

closes #216

Summary

This PR introduces the Soroban/Stellar smart contracts layer to the Scout-Off backend. The workspace is structured as a Rust Cargo workspace under contracts/ with four contracts and a shared utility crate. All public interfaces and auth guards are in place; business logic is left as explicitly-tracked TODOs so each contract can be implemented, tested, and audited in its own follow-up issue.

Contracts

Contract Entry Points Follow-up
register initialize, register_player, update_profile #197
progress initialize, submit_milestone, approve_milestone #198
subscription initialize, subscribe, pay_to_contact, is_subscribed #200
connection initialize, log_trial_offer, get_connection #201

Shared crate (scout-off-shared)

  • errors.rs — unified Error enum (AlreadyInitialized, NotInitialized, Unauthorized, NotFound, InvalidInput, ContractPaused) via #[contracterror], compatible with Soroban's XDR error encoding
  • storage.rs — instance-storage helpers (is_initialized, set_initialized, is_paused, set_paused, bump_instance) with 30-day TTL / 25-day threshold constants
  • events.rs — shared event emitters (emit_initialized, emit_paused)

Design decisions

  • #![no_std] on all contracts — required for WASM targets; soroban-sdk brings its own allocator
  • require_auth() before every state-mutating call — enforces on-chain authorization for all signers
  • Initialization guard on every entry point — contracts revert with NotInitialized if called before initialize, preventing accidental use of an undeployed contract
  • Shared crate instead of copy-paste — error codes and storage keys are defined once, reducing the risk of divergence across contracts

CI

Added a contracts job to .github/workflows/ci.yml that:

  1. Installs the stable Rust toolchain with the wasm32-unknown-unknown target
  2. Restores a Cargo registry cache keyed on Cargo.lock
  3. Builds all contracts as WASM (cargo build --release)

Test plan

pitah23 added 3 commits June 20, 2026 16:18
Installs eslint and @typescript-eslint plugins as devDependencies, adds
tsconfig.eslint.json to include test files, suppresses intentional
control-char regex in sanitizer, and fixes Function type in metrics test.
Literal control bytes in the regex were corrupting the source file,
causing tsc to fail with 'not a module'. charCodeAt filter avoids
any regex and keeps the file clean ASCII.
@Petah1

Petah1 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

resolve conflicts

@pitah23

pitah23 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

just wanted to say working on this codebase has been a genuinely great experience. The project architecture is clean and well thought out, and it made it straightforward to figure out where the Soroban contracts layer should live and how it should connect to the rest of the backend.
The way the off-chain coordinator and indexer are structured gave me a solid foundation to design the contracts workspace around — it was clear what the contracts needed to expose and why. That kind of thoughtful design at the project level doesn't happen by accident, so kudos for that.

@Petah1 Petah1 merged commit 58f231d into scout-off:main Jun 20, 2026
2 checks passed
@Petah1

Petah1 commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Really impressive work on this, @pitah23! 🎉
Scaffolding a full Soroban/Stellar smart contracts layer is no small feat — the decision to structure it as a proper Rust Cargo workspace from day one, rather than bolting it on later, shows real architectural foresight. A few things that stood out:

  • The scout-off-shared crate is a great call. Centralizing the Error enum, storage helpers, and event emitters will save a lot of headache down the road when the individual contracts get their business logic filled in.
  • The require_auth() guard on every state-mutating call and the initialization guard pattern are solid on-chain safety defaults. Easier to ship those from the start than retrofit them later.
  • Adding the contracts CI job with the wasm32-unknown-unknown target and Cargo cache right alongside this scaffold is chef's kiss — the pipeline is honest from commit one.
    The sanitizer fix (swapping the literal control-char regex for a charCodeAt filter to keep the file clean ASCII) was a nice, clean catch too.

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.

Create contracts/ directory with Rust/Soroban workspace scaffold

2 participants