Public security notice: This documentation is intentionally redacted. Sensitive server paths, private keys, secret tokens, and origin network details are removed.
Scoring Model & Categories¶
This page documents how the engine converts raw data into numeric risk scores, including behavioral categories, weights, red flags and credibility.
Component scores and weights¶
Internally, the engine maintains a dictionary of component scores, each representing a behavioral category such as:
- contract / upgrade risk
- liquidity and market structure
- holder distribution and concentration
- governance / transparency
- regulatory posture
- social reputation (
social_data)
Each component is initially expressed as a quality score in the range
1–10 (higher is better). The final risk computation inverts these into a
0–10 risk axis and applies weights. From DeFiRiskAssessor.calculate_risk_scores in
scripts/engine/defi_complete_risk_assessment_clean.py:
```python print(f" 📊 Calculating final risk score...") weighted_component_risk = 0.0 social_score_contribution = 0.0 weight_sum = sum(float(w) for w in self.WEIGHTS.values()) or 1.0
for component, weight in self.WEIGHTS.items(): # Component scores are quality scores (1..10, higher=better). # Convert to risk axis (0..10, higher=worse). normalized_risk = ((10.0 - component_scores[component]) / 9.0) * 10.0 normalized_risk = max(0.0, min(10.0, normalized_risk)) weighted_risk = normalized_risk * float(weight) weighted_component_risk += weighted_risk ```
The final “base” risk score is then scaled into the configured range
0..BASE_RISK_MAX:
python
base_risk_score = (weighted_component_risk / weight_sum) * (float(self.BASE_RISK_MAX) / 10.0)
social_score_contribution = (social_score_contribution / weight_sum) * (float(self.BASE_RISK_MAX) / 10.0)
The social_score_contribution is tracked separately for reporting.
Red flags and additive boosts¶
Beyond structural component scores, the engine maintains a list of red flags. Each flag has:
- a
checkkey (e.g.is_proxy_contract,eu_unlicensed_stablecoin), and - a numeric
risk_boost.
Default definition (excerpt from calculate_risk_scores, which rebuilds the
table when it is missing; the DeFiRiskAssessor constructor sets the same list):
python
if not hasattr(self, 'RED_FLAGS') or not self.RED_FLAGS:
self.RED_FLAGS = [
{'check': 'is_proxy_contract', 'risk_boost': 20},
{'check': 'has_honeypot_pattern', 'risk_boost': 30},
...
{'check': 'eu_unlicensed_stablecoin', 'risk_boost': 50},
{'check': 'eu_regulatory_issues', 'risk_boost': 40},
{'check': 'mica_non_compliant', 'risk_boost': 35},
{'check': 'mica_no_whitepaper', 'risk_boost': 0}
]
Score scale and risk bands¶
The total risk score runs on a 0–150 scale (not 0–100). Band thresholds, identical in the
engine (classify_risk) and the portal adapter (RISK_BAND_THRESHOLDS):
| Band | Score range |
|---|---|
| Low | 0–50 |
| Medium | 51–100 |
| High | 101–120 |
| Extreme | 121–150 |
One hard override exists: the eu_unlicensed_stablecoin red flag forces the score to 150
(Extreme) regardless of the component scores.
Confidence¶
The confidence percentage is data coverage: successful_sources / expected_sources * 100
for the run, with every per-component confidence clamped so it never exceeds the overall value.
It is not statistical certainty about the verdict. Interpretation bands used in-product:
High ≥85%, Moderate 60–84%, Low <60% (review manually). A component whose sources all failed
scores a neutral 5.0 with confidence 0 and still enters the weighted total — the portal surfaces
this as a "Partial data" chip.
Output suppression by plan¶
Free-tier output is limited to primary providers, market/behavior summaries, and no red flags; Basic excludes social-provider signals; Pro/Enterprise receive full output. A crashed engine run is shown as Score Unavailable, never as a risk verdict.
During scoring, the engine:
- Skips flags without a positive boost, and the special
eu_unlicensed_stablecoinflag, which is applied as a hard override instead. - Sums
raw_red_flag_boostfrom all flags actually present for this token. - Caps that sum at
RED_FLAG_MAX_ADDITIVEto producered_flag_score, so each flag adds its configured boost until the cap is reached.
python
raw_red_flag_boost = 0.0
for rf in self.RED_FLAGS:
...
boost = self.safe_float(rf.get('risk_boost', 0), 0.0)
if boost <= 0:
continue
# Unlicensed stablecoin is handled as a hard override below.
...
if flag_key in red_flags:
raw_red_flag_boost += boost
...
red_flag_score = min(float(self.RED_FLAG_MAX_ADDITIVE), raw_red_flag_boost)
This additive score is then combined with the base score to produce the total risk score.
Market-structure penalties and native token discounts¶
The engine applies additional contextual modifiers:
- Market-structure penalties for low holders, low volume, small market cap with weak liquidity, etc.
- Native chain token discounts when the token is the canonical gas / base asset for a chain.
Example, from the same method:
python
market_penalty_map = {
'low_holders': ...,
'very_low_holders': ...,
'low_volume_24h': ...,
'low_market_cap_weak_liquidity': ...,
'low_market_cap_weak_liquidity_and_holders': ...,
}
for flag_key, penalty in market_penalty_map.items():
...
if flag_key in set(red_flags or []):
market_structure_penalty += penalty_value
...
if 'native_chain_token' in context_flags_set:
...
The native-chain discount defaults to 3.0 points (NATIVE_CHAIN_TOKEN_RISK_DISCOUNT),
is clamped between 0 and 8, and is not applied to wrapped tokens.
These modifiers ensure that:
- Extremely thin or illiquid markets are treated as higher risk.
- Legitimate chain-native tokens are not unfairly penalized by generic rules.
Credibility / confidence¶
While the numeric score answers “how risky is this token?”, the credibility dimension answers “how reliable is this score?”.
Credibility is influenced by:
- how many independent data sources contributed to each category,
- whether values came from live APIs, cache, Token Data Viewer, or fallback data,
- whether certain critical providers (sanctions / compliance) were reachable.
The engine tracks provenance for each metric, and the final JSON report includes information about:
- which sources were used,
- which were skipped or failed,
- whether specific values are estimates.
Downstream dashboards can surface this as a confidence bar or label, prompting analysts to manually review low-credibility assessments even if the numeric score looks benign.
Social score as a dedicated component¶
The social score (social_data) is treated as one of the weighted components,
but its contribution is also computed separately for transparency, inside the
same weighting loop:
python
weighted_component_risk = 0.0
social_score_contribution = 0.0
...
for component, weight in self.WEIGHTS.items():
...
if component == 'social_data':
social_score_contribution = weighted_risk
After scaling, the engine subtracts social_score_contribution from the total
and stores the result as total_score_minus_social next to total_risk_score,
so reports can show how much of the risk is driven purely by social / news
signals.
See Social Score System for a deeper explanation of how social data is collected and analyzed.