This contract is for educational and testnet use. Review the following before any mainnet deployment.
See the Admin Role document for details on what the initialize(admin) value records, what the admin can and cannot do today, and future admin design considerations.
See the Admin & Emergency Mechanism Threat Model for a security analysis of malicious admin, compromised admin, accidental pause, and blocked-withdrawal scenarios, including mitigations and trust assumptions.
| Function | Description |
|---|---|
initialize(admin) |
One-time setup; records the admin address |
deposit(user, amount) |
Add funds to a user's vault |
withdraw(user, amount) |
Remove funds from a user's vault |
get_balance(user) |
Query available (unlocked) balance |
lock_funds(user, amount, unlock_time) |
Lock funds until a Unix timestamp |
get_locked_balance(user) |
Query locked balance |
can_withdraw(user) |
Check if locked funds are withdrawable |
Install the following before you begin:
-
Rust (latest stable)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Soroban CLI
cargo install --locked soroban-cli
-
WASM target
rustup target add wasm32-unknown-unknown
Compile the contract to a WASM binary:
# Debug build
cargo build --target wasm32-unknown-unknown
# Optimized release build (recommended for deployment)
cargo build --target wasm32-unknown-unknown --release
# Optimized release build with an immediate WASM size report
make build-releaseThe compiled .wasm file will be at:
target/wasm32-unknown-unknown/release/savings_vault.wasm
Soroban contract size affects upload and deployment costs and can reveal unexpected binary growth. Use the release wrapper above to build and print the artifact size in both human-readable units and exact bytes:
WASM artifact: target/wasm32-unknown-unknown/release/savings_vault.wasm
WASM size: 5.73 KiB (5871 bytes)
To report the size of an existing release artifact without rebuilding it, run:
make wasm-sizeThe reporting command exits with an error and identifies the expected path when the WASM file is missing. CI pipelines should run make build-release (or make wasm-size after their release build) so contract-size changes remain visible in build logs.
Run the full unit test suite:
cargo testAll tests run natively (no WASM needed) using the Soroban SDK test utilities.
Before opening a pull request, run the single local verification command:
make verifyThis runs the same checks contributors are asked to confirm in the PR template:
cargo fmt --checkcargo clippy --tests -- -D warningscargo test --workspacecargo build --release --target wasm32-unknown-unknown
See CONTRIBUTING.md for details and for running each step individually.
Common tasks are available via make:
make verify # Format, lint, test, and release WASM build
make build-release # Optimized WASM build with size report
make wasm-size # Report size of an existing release WASMsoroban network add \
--global testnet \
--rpc-url https://soroban-testnet.stellar.org:443 \
--network-passphrase "Test SDF Network ; September 2015"soroban keys generate --global deployer --network testnet
soroban keys address deployerFund the account at Stellar Friendbot.
soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/savings_vault.wasm \
--source deployer \
--network testnetSave the returned Contract ID — you'll need it to invoke functions.
soroban contract invoke \
--id YOUR_CONTRACT_ID \
--source deployer \
--network testnet \
-- \
initialize \
--admin deployer# Deposit 1000 units
soroban contract invoke \
--id YOUR_CONTRACT_ID \
--source deployer \
--network testnet \
-- \
deposit \
--user deployer \
--amount 1000
# Check balance
soroban contract invoke \
--id YOUR_CONTRACT_ID \
--source deployer \
--network testnet \
-- \
get_balance \
--user deployerstellar-pocketpay-contracts/
├── Cargo.toml # Workspace root
├── .gitignore
├── README.md
└── contracts/
└── savings_vault/
├── Cargo.toml # Contract crate
└── src/
├── lib.rs # Contract implementation
└── test.rs # Unit tests
- Architecture Documentation – Overview of project structure, state management, storage, SDK integration, and future extension points.
- Admin Role – Details on the admin address, current capabilities, and future design considerations.
- Admin & Emergency Mechanism Threat Model – Security analysis of malicious admin, compromised admin, accidental pause, and blocked-withdrawal scenarios.
- Failure Mode Catalogue – Summary of safe-failure behavior, expected errors, affected functions, and related tests for vault operations.
- Traceability Table Guide – Standard format for mapping PR changes to issue acceptance criteria, with worked examples.
This contract is for educational and testnet use. Review the following before any mainnet deployment.
- Every state-changing function calls
require_auth()on the user's address. - Only the signing user can deposit, withdraw, or lock their own funds.
- Zero and negative amounts are rejected for deposits, withdrawals, and locks.
- Withdrawals exceeding the available balance are rejected.
- Lock amounts exceeding the available balance are rejected.
- Unlock times in the past are rejected.
initialize()can only be called once; subsequent calls panic.
- User balances are stored in persistent storage (survives ledger expiry longer).
- Admin and initialization flags use instance storage (tied to contract lifetime).
- No real token transfers: This contract tracks balances internally but does not yet integrate with the Stellar Asset Contract (SAC) for actual XLM/token transfers. A production version should call the token contract's
transfer()function. - Single unlock time: Locking funds multiple times overwrites the previous unlock timestamp. A production version might use per-lock entries.
- No admin recovery: There is no mechanism for the admin to recover or migrate funds.
- No upgrade mechanism: The contract does not implement
upgrade(). Consider adding this for mainnet.
- Testnet RPC:
https://soroban-testnet.stellar.org:443 - Network passphrase:
Test SDF Network ; September 2015 - Friendbot (free testnet XLM):
https://friendbot.stellar.org - Soroban Explorer: stellar.expert
- Always test thoroughly on testnet before considering mainnet deployment.
- Monitor contract storage TTL and extend as needed using
soroban contract extend.
Contributions are welcome! This project is intentionally beginner-friendly.
See CONTRIBUTING.md for the full guide, including:
- How to run local verification (
make verify) - How to format code (
cargo fmt) - How to lint code (
cargo clippy --tests -- -D warnings) - How to run the test suite (
cargo test --workspace) - PR checklist and commit message conventions
Every pull request must use the PR template, which requires:
- A reference to the issue being fixed (
Closes #N) - A list of contract functions added, modified, or removed
- A description of tests added or updated
- A traceability table mapping each acceptance criterion to changed functions, tests, and edge cases
- A security considerations section (with checklist for contract changes)
- Confirmation that
make verifypasses (or equivalentlycargo fmt --check,cargo clippy --tests -- -D warnings, andcargo test --workspace) - CI green before requesting review
Quick start:
# Fork & clone, then verify everything is green before opening a PR
make verifyMIT