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
Read-only function. Returns `wallet`'s cross-asset aggregate risk score — a weighted average computed live from every asset pair the wallet has a `RiskScore` for. Always recomputed from current per-pair scores, never served from a stale cache. Returns `ScoreNotFound` if the wallet has no scores.
Sets the weight used for `asset_pair` in the aggregate risk computation. Defaults to `1` (simple average) for any pair the admin hasn't configured. A weight of `0` excludes the pair from the aggregate's denominator. Admin only.
78
+
79
+
### `get_pair_weight(asset_pair: Symbol) -> u32`
80
+
Read-only lookup of the configured weight for `asset_pair`.
81
+
73
82
### `RiskScore` Structure
74
83
75
84
```rust
@@ -82,6 +91,55 @@ pub struct RiskScore {
82
91
}
83
92
```
84
93
94
+
### `AggregateRiskScore` Structure
95
+
96
+
A wallet that is moderately suspicious across several asset pairs poses a higher *portfolio-level* risk than its individual per-pair scores suggest in isolation. `AggregateRiskScore` expresses that risk on-chain:
97
+
98
+
```rust
99
+
pubstructAggregateRiskScore {
100
+
pubaggregate_score:u32, // 0-100, weighted average across all pairs
101
+
pubpair_count:u32, // number of distinct pairs the wallet has a score for
`pair_weight[i]` defaults to `1` for every pair (a plain average) unless the admin sets a different weight via `set_pair_weight`. A pair with weight `0` is excluded from the denominator — its score still counts toward `pair_count`, `max_pair_score`, the flag counts, and `last_updated`, but not toward `aggregate_score`.
A wallet scoring 60-70 on three pairs individually might not breach the per-pair `RiskThreshold` (default 75), but the aggregate view makes the *combined* exposure visible to any contract or dashboard that queries `get_aggregate_score` — without needing to fetch and average every pair manually.
140
+
141
+
`get_aggregate_score` iterates the wallet's full pair list, so its cost is O(N) in the number of distinct pairs the wallet has scores for. The contract is designed around a practical maximum of `MAX_WALLET_PAIRS` (20) pairs per wallet; this is documented as a constant but not enforced on-chain.
142
+
85
143
## Security Features
86
144
87
145
1.**Authorization Checks**: Only the authorised LedgerLens service account can submit scores
@@ -249,6 +307,7 @@ pub struct RiskScore {
249
307
250
308
-`score` — `(wallet, asset_pair) -> (score, benford_flag, ml_flag, confidence, timestamp)`, emitted on every `submit_score`
251
309
-`svc_upd` — emitted when the admin rotates the authorised service address
310
+
-`pw_upd` — `(asset_pair) -> weight`, emitted when the admin sets a pair's aggregate-risk weight via `set_pair_weight`
252
311
253
312
`api` (or a dedicated indexer in `data`) should subscribe to these for audit trails and to keep an off-chain cache in sync with on-chain state.
0 commit comments