TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Centurylong/sanctifier/llms.txt
Use this file to discover all available pages before exploring further.
contracts/ directory of the Sanctifier repository contains a curated set of Soroban smart contracts that serve two purposes: some are hardened reference implementations you can adapt directly in your projects, while others are intentionally insecure and exist only to exercise Sanctifier’s detectors and formal verification harnesses. Every contract is a real, compilable Rust crate that targets wasm32-unknown-unknown.
amm-pool
Hardened AMM with slippage protection, MEV resistance, k-invariant proofs, and 14 property tests.
reentrancy-guard
no_std-compatible reentrancy lock with four Kani-verified state-machine proofs.runtime-guard-wrapper
Wraps any contract with pre/post execution guards, metrics collection, and audit-trail events.
protected-vault
Vault contract integrating
reentrancy-guard; includes integration tests that catch simulated attacks.token-invariants
Token contract with
#[sanctify::invariant] annotations and Kani harnesses for balance and supply proofs.sep41-token-invariants
SEP-41 standard token with formal invariant proofs covering transfer, mint, burn, and approve flows.
vulnerable-contract
Intentionally insecure contract used to validate Sanctifier’s static-analysis detectors.
token-with-bugs
Token with deliberate bugs (missing auth, no init guard) for detector regression testing.
kani-poc
Proof-of-concept Kani harnesses demonstrating the pure-function verification strategy.
zk-verifier
On-chain Groth16 ZK proof verifier using
ark-groth16 and ark-bls12-381.Using contracts as templates
Clone the repository and copy any hardened contract crate into your workspace. Each crate is independent (its ownCargo.toml) and depends only on soroban-sdk and, where relevant, the workspace-local reentrancy-guard crate. Add the workspace path dependency then run the standard Soroban build:
amm-pool
Location:contracts/amm-pool/
A fully hardened Automated Market Maker (AMM) liquidity pool that implements the constant product formula (k = reserve_a × reserve_b). This contract is intended as a production-ready starting point for any DEX integration on Stellar.
Key security patterns demonstrated:
- Slippage protection — The
swapfunction accepts amin_amount_outparameter; the transaction reverts if the calculated output falls below it, preventing sandwich attacks. - MEV resistance — A
deadline(Unix timestamp) parameter causes stale transactions to revert automatically. - K-invariant enforcement — After every swap the contract explicitly verifies
new_k >= old_k, providing an on-chain assertion that the constant product property is never violated. - Checked arithmetic throughout — All balance and reserve math uses
checked_add,checked_mul, andchecked_div; no raw+/*operators appear in financial code paths.
| Suite | Count | Tool |
|---|---|---|
| Unit tests | 4 | cargo test |
| Property tests | 14 | proptest |
| Formal verification harnesses | 7 | Kani |
reentrancy-guard
Location:contracts/reentrancy-guard/
A lightweight, #![no_std]-compatible reentrancy guard crate for Soroban. It stores a single u32 lock flag under the storage key RE_GRD in Soroban instance storage. Calling enter() while the flag is already set causes an immediate panic!("reentrancy detected"), aborting the transaction before any state mutation can occur.
Key security patterns demonstrated:
- Storage-backed mutex — The lock survives cross-contract call boundaries because it lives in instance storage, not a local variable.
- Pure state-transition core —
enter_pureandexit_pureare side-effect-free functions that can be exhaustively verified by Kani without any host-type stubs. no_stdcompatibility — Works in any Soroban contract without pulling instd.
| Harness | Property |
|---|---|
verify_enter_fails_when_locked | Entering a locked guard always returns Err |
verify_enter_succeeds_when_unlocked | Entering an unlocked guard always returns Ok(Locked) |
verify_exit_always_unlocks | Exit always transitions to Unlocked |
verify_guard_state_machine | Exhaustive two-state transition check |
runtime-guard-wrapper
Location:contracts/runtime-guard-wrapper/
A Soroban contract that wraps any other deployed contract and enforces runtime validation before and after every function call. It is the reference integration for the sanctifier-guards crate’s guard_invariant_result! macro, which emits structured inv_fail audit events when an invariant breaks.
Key security patterns demonstrated:
- Pre-execution guards — Verifies the wrapped contract address is configured and that instance-storage integrity keys are present before forwarding any call.
- Post-execution invariant checks — After each guarded call the wrapper asserts the
invariants_checkedcounter strictly advanced; a stuck counter surfaces as aGuardError::InvariantCounterStuckevent. - Audit-trail events — The
guard_invariant_result!macro publishesinv_failevents with a machine-readable payload; off-chain indexers can subscribe to a single topic to observe invariant failures across all instrumented contracts. - Bounded storage — The call log is capped at 100 entries and metrics at 1,000 entries, preventing the instance-storage capacity DoS described in
SOB-2024-025.
protected-vault
Location:contracts/protected-vault/
A minimal vault contract that integrates the reentrancy-guard crate. The deposit and withdraw entry points both call guard.enter() before touching storage, making it impossible for a malicious callee to re-enter the vault mid-operation. The crate includes an integration test that simulates a reentrancy attack and asserts the guard causes the transaction to revert.
Key security patterns demonstrated:
- Direct integration of
reentrancy-guardas a workspace dependency. - Positive access-control (
amount > 0assertion before state mutation). - Demonstrates the pattern described in vulnerability entry
SOB-2024-015.
token-invariants
Location:contracts/token-invariants/
A token contract whose pure business logic is separated into a pure module so that Kani can reason over it without needing host-type stubs. The contract layer uses #[sanctify::invariant(...)] annotations that sanctifier verify picks up and dispatches to the Z3 SMT backend.
Key security patterns demonstrated:
- Core logic separation —
pure::{mint_pure, burn_pure, transfer_pure}contain noEnv,Address, orSymboldependencies, making them directly Kani-verifiable. - Annotated invariants —
#[sanctify::invariant(balance >= 0)]and supply-conservation assertions are declared inline and automatically checked bysanctifier verify. - Kani harnesses — Located in
src/kani_proofs.rs; verify overflow safety and conservation properties.
sep41-token-invariants
Location:contracts/sep41-token-invariants/
Extends token-invariants to implement the full SEP-41 fungible token interface including transfer_from, approve, and allowance management. Kani harnesses cover the allowance race condition (SOB-2024-017) and the transfer_from allowance check (SOL-2024-009).
Key security patterns demonstrated:
- Allowance decrement enforced before balance mutation, preventing
SOL-2024-009. - Allowance race condition guard (set to zero before non-zero), preventing
SOB-2024-017. - All five token operations (
transfer,transfer_from,approve,mint,burn) have Kani harnesses insrc/kani_proofs.rs.
vulnerable-contract
Location:contracts/vulnerable-contract/
Demonstrates several of the most common Soroban security pitfalls, including:
set_adminwithout anyrequire_authcall (triggers findingS001/SOL-2024-001).- A contrasting
set_admin_securefunction showing the correct pattern.
tests/ directory contains golden-snapshot tests (insta) that lock in the exact findings, so any detector regression causes CI to fail.
token-with-bugs
Location:contracts/token-with-bugs/
A token contract with deliberate security defects used to test and maintain the accuracy of Sanctifier’s built-in detectors:
initializedoes not persistadmin,name, orsymbol, leaving the initialization guard incomplete (triggersSOL-2024-001pattern).- Missing
require_authon privileged entry points. - Intentional arithmetic issues for
S003detector coverage.
kani-poc
Location:contracts/kani-poc/
A proof-of-concept crate demonstrating the Core Logic Separation pattern for Kani verification. Because Kani cannot model the Soroban host types (Env, Address, Symbol) directly, this contract extracts pure initialization and token-operation logic into host-free functions that Kani can reason about exhaustively.
Key patterns demonstrated:
initialize_pure(is_initialized: bool) -> Result<(), &'static str>— pure function verified to reject double-initialization for all possible boolean inputs.- Shows how to structure a contract so the security-critical arithmetic is separated from the host-interaction layer, enabling Kani coverage without stubs.
zk-verifier
Location:contracts/zk-verifier/
An on-chain Groth16 zero-knowledge proof verifier built with ark-groth16 and ark-bls12-381. The contract accepts a serialized verifying key (stored on initialization) and a proof blob (passed per invocation), and returns a boolean indicating whether the proof is valid.
Key security patterns demonstrated:
- Storing large cryptographic artifacts (verifying keys) in persistent storage rather than instance storage, avoiding
SOB-2024-025. - Using
ark-serialize::CanonicalDeserializeto safely parse untrusted byte inputs. wee_allocas a global allocator for lean WASM output.
The
zk-verifier contract depends on ark-* crates that require alloc. Compile with --release to keep WASM size manageable; debug builds may exceed Soroban’s contract size limits.