Skip to content

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 check key (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:

  1. Skips flags without a positive boost, and the special eu_unlicensed_stablecoin flag, which is applied as a hard override instead.
  2. Sums raw_red_flag_boost from all flags actually present for this token.
  3. Caps that sum at RED_FLAG_MAX_ADDITIVE to produce red_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.