Summary
LedgerLens's stated goal is to make fraud signals composable with other Soroban protocols — AMMs, lending platforms, DEX aggregators. But there is currently no standardized interface that third-party contracts can target. Every integrator must reverse-engineer the current get_score function signature and the RiskScore struct, and any future breaking change to either will silently break all integrations.
This issue defines and implements a ILedgerLensScore composability interface — a stable, versioned ABI contract that acts as the canonical integration point for the entire Stellar DeFi ecosystem. The interface is inspired by ERC-standards in Ethereum but adapted to Soroban's invocation model.
Scope of Work
1. Interface Specification Document — docs/interface-spec.md
Write a complete specification covering:
- The canonical function signatures external contracts must call.
- The exact
RiskScore struct layout (field ordering matters for XDR serialization).
- Versioning policy (how callers detect interface version).
- Error code stability guarantees (which error codes are stable and which may change).
- Recommended integration patterns (gate-on-threshold, cache TTL, fallback behaviour when
ScoreNotFound).
2. Stable Getter Facade — lib.rs
Add a query_risk_gate(wallet, asset_pair, gate_threshold) function designed specifically for cross-contract calls:
/// Returns true if the wallet's risk score is BELOW gate_threshold
/// (i.e. the wallet is considered safe to proceed).
/// Returns false if score >= gate_threshold OR if no score exists.
/// This function never panics and never returns an Error —
/// it is designed to be called from within other contracts' guard clauses.
pub fn query_risk_gate(
env: Env,
wallet: Address,
asset_pair: Symbol,
gate_threshold: u32,
) -> bool
This function must be side-effect free and infallible — external contracts can call it in their own authorization logic without worrying about error propagation.
3. Interface Version Registry — lib.rs
/// Returns a map of interface capability names to boolean support flags.
/// Allows cross-contract callers to detect which features are available
/// without hardcoding contract version numbers.
pub fn supports_interface(env: Env, capability: Symbol) -> bool
Registered capabilities (initial set):
4. Reference Integration Example — examples/amm_gate.rs
Write a minimal reference Soroban contract (LedgerLensGatedAMM) that demonstrates how to call query_risk_gate before processing a swap. This is a documentation artifact — it does not need to be a complete AMM, just the guard-clause integration pattern.
fn swap(env: Env, user: Address, amount: i128) -> Result<(), AmmError> {
let llens_contract = /* LedgerLens contract ID from storage */;
let client = LedgerLensScoreContractClient::new(&env, &llens_contract);
let is_safe = client.query_risk_gate(&user, &symbol_short!("XLM_USDC"), &75u32);
if !is_safe {
return Err(AmmError::HighRiskWallet);
}
// ... rest of swap logic
}
5. Interface Stability Test Suite
Add a dedicated test_interface.rs that tests the interface contract rather than the implementation:
| Test name |
What it verifies |
test_query_risk_gate_safe_wallet |
Score 40, threshold 75 → true |
test_query_risk_gate_risky_wallet |
Score 80, threshold 75 → false |
test_query_risk_gate_at_threshold |
Score 75, threshold 75 → false (≥ threshold = not safe) |
test_query_risk_gate_no_score_returns_false |
Conservative default for unknown wallets |
test_query_risk_gate_never_panics |
Fuzz 1000 random inputs — no panic |
test_supports_interface_score |
supports_interface("score") = true |
test_supports_interface_unknown |
supports_interface("foobar") = false |
test_risk_score_xdr_stability |
Serialize and deserialize RiskScore — field order stable |
test_error_codes_stable |
All error discriminant values match documented constants |
Security Considerations
query_risk_gate must never panic — a panic in a cross-contract call wastes the calling contract's gas and could be exploited by an attacker to disable the calling protocol's security guard.
- The infallible design (
→ bool, not → Result<bool, Error>) means ScoreNotFound must return false (conservative: treat unknown wallets as potentially risky). Document this explicitly.
- Interface capability symbols must be stable across versions — removing a capability is a breaking change.
Documentation Required
docs/interface-spec.md — canonical integration guide (the primary deliverable of this issue).
- Rustdoc on
query_risk_gate and supports_interface.
examples/amm_gate.rs with explanatory comments.
- Blog-post-style section in
README.md under Composability with a code snippet showing the AMM pattern.
For Contributors
Area of specialty needed: Advanced Soroban; DeFi protocol architecture; cross-contract invocation patterns; interface/ABI stability design. Experience integrating with or building AMMs or lending protocols on any EVM-compatible chain or Cosmos is highly transferable.
How to contribute:
- Start by writing
docs/interface-spec.md as a PR draft and request design review before implementing.
- Branch:
feat/composability-interface.
- The
examples/amm_gate.rs reference implementation must compile against the current SDK version (add it to the workspace Cargo.toml as a separate [[example]]).
Estimated effort: 35–55 hours (specification writing + implementation + testing).
Summary
LedgerLens's stated goal is to make fraud signals composable with other Soroban protocols — AMMs, lending platforms, DEX aggregators. But there is currently no standardized interface that third-party contracts can target. Every integrator must reverse-engineer the current
get_scorefunction signature and theRiskScorestruct, and any future breaking change to either will silently break all integrations.This issue defines and implements a
ILedgerLensScorecomposability interface — a stable, versioned ABI contract that acts as the canonical integration point for the entire Stellar DeFi ecosystem. The interface is inspired by ERC-standards in Ethereum but adapted to Soroban's invocation model.Scope of Work
1. Interface Specification Document —
docs/interface-spec.mdWrite a complete specification covering:
RiskScorestruct layout (field ordering matters for XDR serialization).ScoreNotFound).2. Stable Getter Facade —
lib.rsAdd a
query_risk_gate(wallet, asset_pair, gate_threshold)function designed specifically for cross-contract calls:This function must be side-effect free and infallible — external contracts can call it in their own authorization logic without worrying about error propagation.
3. Interface Version Registry —
lib.rsRegistered capabilities (initial set):
symbol_short!("score")— basicget_score/submit_scoresymbol_short!("history")—get_score_historysymbol_short!("batch")—submit_scores_batchsymbol_short!("gate")—query_risk_gatesymbol_short!("aggr")— aggregate risk (from issue Build cross-asset aggregate risk engine: weighted portfolio-level risk score per wallet #11, if merged)4. Reference Integration Example —
examples/amm_gate.rsWrite a minimal reference Soroban contract (
LedgerLensGatedAMM) that demonstrates how to callquery_risk_gatebefore processing a swap. This is a documentation artifact — it does not need to be a complete AMM, just the guard-clause integration pattern.5. Interface Stability Test Suite
Add a dedicated
test_interface.rsthat tests the interface contract rather than the implementation:test_query_risk_gate_safe_wallettruetest_query_risk_gate_risky_walletfalsetest_query_risk_gate_at_thresholdfalse(≥ threshold = not safe)test_query_risk_gate_no_score_returns_falsetest_query_risk_gate_never_panicstest_supports_interface_scoresupports_interface("score")= truetest_supports_interface_unknownsupports_interface("foobar")= falsetest_risk_score_xdr_stabilityRiskScore— field order stabletest_error_codes_stableSecurity Considerations
query_risk_gatemust never panic — a panic in a cross-contract call wastes the calling contract's gas and could be exploited by an attacker to disable the calling protocol's security guard.→ bool, not→ Result<bool, Error>) meansScoreNotFoundmust returnfalse(conservative: treat unknown wallets as potentially risky). Document this explicitly.Documentation Required
docs/interface-spec.md— canonical integration guide (the primary deliverable of this issue).query_risk_gateandsupports_interface.examples/amm_gate.rswith explanatory comments.README.mdunder Composability with a code snippet showing the AMM pattern.For Contributors
Area of specialty needed: Advanced Soroban; DeFi protocol architecture; cross-contract invocation patterns; interface/ABI stability design. Experience integrating with or building AMMs or lending protocols on any EVM-compatible chain or Cosmos is highly transferable.
How to contribute:
docs/interface-spec.mdas a PR draft and request design review before implementing.feat/composability-interface.examples/amm_gate.rsreference implementation must compile against the current SDK version (add it to the workspaceCargo.tomlas a separate[[example]]).Estimated effort: 35–55 hours (specification writing + implementation + testing).