You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Admin sets the time-lock delay applied to future proposals, bounded to `[MIN_UPGRADE_DELAY_SECS, MAX_UPGRADE_DELAY_SECS]` (48 hours – 14 days); out-of-range values are rejected with `InvalidUpgradeDelay`. Defaults to 48 hours.
Admin sets the cooldown enforced between accepted submissions for the same `(wallet, asset_pair)`, bounded to `[MIN_COOLDOWN_SECS, MAX_COOLDOWN_SECS]` (1 minute – 24 hours); out-of-range values are rejected with `InvalidCooldown`. Defaults to 1 hour. See [Rate Limiting](#rate-limiting).
Admin-only emergency escape hatch. Immediately clears the stored cooldown deadline for `(wallet, asset_pair)`, so the next `submit_score` / `submit_scores_batch` call for that pair is accepted regardless of how recently the last one was. Intended for correcting a known-bad score right away, not for routine use. Emits `rl_ovrd`.
Read-only lookup of the ledger timestamp of the last accepted submission for `(wallet, asset_pair)`, or `0` if none has ever been accepted (or it was cleared by `override_rate_limit`).
114
+
106
115
### `RiskScore` Structure
107
116
108
117
```rust
@@ -200,6 +209,20 @@ Soroban contracts can be upgraded by the admin via `update_current_contract_wasm
200
209
201
210
The time-lock is computed from `env.ledger().timestamp()` (deterministic, not caller-settable) and re-verified at execution time — never cached. The configurable delay is bounded to `[MIN_UPGRADE_DELAY_SECS, MAX_UPGRADE_DELAY_SECS]`; **raising** it is always safe, while **lowering** it shortens the veto window and should require community consensus. See [`SECURITY.md`](SECURITY.md#upgrade-governance--threat-model) for the full threat model and monitoring guidance.
202
211
212
+
## Rate Limiting
213
+
214
+
A compromised or malfunctioning off-chain service could otherwise flood the contract with submissions for the same `(wallet, asset_pair)`, exhausting storage rent, overwhelming indexers, and poisoning the score signal with rapid fluctuations. LedgerLens enforces a configurable **cooldown** between accepted submissions for any given wallet/asset-pair to bound that blast radius.
215
+
216
+
**The flow:**
217
+
218
+
1. On every `submit_score` (and per-entry in `submit_scores_batch`), the contract compares `env.ledger().timestamp()` against the pair's last accepted submission time plus the configured cooldown.
219
+
2. If the cooldown hasn't elapsed, `submit_score` returns `RateLimitExceeded`; in `submit_scores_batch` the offending entry is silently skipped (the rest of the batch still processes) and counted as not accepted.
220
+
3. A successful submission updates the pair's last-submit timestamp, starting the next cooldown window.
221
+
222
+
The cooldown defaults to **1 hour** and is admin-configurable via `set_cooldown`, bounded to `[MIN_COOLDOWN_SECS, MAX_COOLDOWN_SECS]` (1 minute – 24 hours) so the admin can neither disable rate limiting entirely nor lock a pair out indefinitely. For situations that need an immediate re-score (e.g. correcting a known-bad score), the admin can call `override_rate_limit` to clear a specific pair's cooldown rather than lowering the global setting.
223
+
224
+
Like the upgrade time-lock, the cooldown deadline is computed from `env.ledger().timestamp()` — deterministic and not caller-settable — so it cannot be bypassed by manipulating submission metadata such as the `timestamp` field on `RiskScore` itself.
225
+
203
226
## Composability
204
227
205
228
LedgerLens is only useful if other protocols can actually *act* on its scores. A risk score that lives in isolation is a dashboard widget; a risk score that an AMM, a lending market, or a DEX aggregator can read mid-transaction is a shared fraud-prevention layer for the entire Stellar DeFi ecosystem.
@@ -249,6 +272,7 @@ A complete, compiling reference contract lives in [`examples/amm_gate.rs`](examp
249
272
3.**Bounded Values**: Scores and confidence are constrained to the 0-100 range
250
273
4.**Overflow Protection**: Safe math operations with overflow checks
251
274
5.**Time-Locked Upgrades**: Contract WASM upgrades require a mandatory delay (≥48 h) with a public proposal anyone can inspect and an admin veto — see [Upgrade Governance](#upgrade-governance)
275
+
6.**Submission Rate Limiting**: A configurable per-`(wallet, asset_pair)` cooldown (default 1 h) bounds how often the service account can overwrite a score — see [Rate Limiting](#rate-limiting)
Copy file name to clipboardExpand all lines: SECURITY.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,6 +54,7 @@ We follow [Responsible Disclosure](https://en.wikipedia.org/wiki/Coordinated_vul
54
54
| Score poisoning via out-of-range data |`score` and `confidence` clamped to 0-100 on-chain |
55
55
| DoS via unbounded storage | History ring buffer capped at `HISTORY_MAX_DEPTH` (10) per pair |
56
56
| Large batch denial of service | Batch size capped at `MAX_BATCH_SIZE` (20) per invocation |
57
+
| Compromised service floods a pair with submissions | Per-`(wallet, asset_pair)` cooldown (`RateLimitExceeded`); admin-bounded `[MIN_COOLDOWN_SECS, MAX_COOLDOWN_SECS]`, with `override_rate_limit` as an audited emergency escape hatch |
57
58
| Silent malicious contract upgrade | Time-locked upgrade governance (see below): mandatory delay + on-chain proposal anyone can inspect, plus admin veto |
0 commit comments