ability-analysis
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth…
Trigger Pattern ORACLE flag (required) - Inject Into Breadth agents, depth-external, depth-edge-case
$ npx -y skills add PlamenTSV/plamen --skill oracle-analysis --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/oracle-analysisContext preview
The summary Claude sees to decide when to auto-load this skill.
Trigger Pattern ORACLE flag (required) - Inject Into Breadth agents, depth-external, depth-edge-case
name: "oracle-analysis" description: "Trigger Pattern ORACLE flag (required) - Inject Into Breadth agents, depth-external, depth-edge-case"
> **Trigger Pattern**: ORACLE flag (required) > **Inject Into**: Breadth agents, depth-external, depth-edge-case > **Purpose**: Analyze all oracle integrations in Aptos Move protocols for staleness, decimal errors, zero/negative prices, confidence intervals, multi-oracle aggregation, and failure modes
For every oracle the protocol consumes:
**STEP PRIORITY**: Steps 6 (Failure Modes) and 5c (Deviation Reference) are where HIGH/CRITICAL severity findings most commonly hide. Do NOT rush these steps. If constrained, skip conditional sections (4a-4d, 5a) before skipping 5c or 6.
Enumerate ALL oracle data sources the protocol reads:
| Oracle | Type | Module Path | Functions Called | Consumers (protocol functions) | Update Frequency | Freshness Guarantee | |--------|------|-------------|-----------------|-------------------------------|-----------------|---------------------| | {name} | Pyth / Switchboard / Custom / On-chain TWAP | {module::path} | {get_price / get_result / etc.} | {list all} | {expected} | {documented or UNKNOWN} |
**Aptos oracle landscape**:
**For each oracle**: What decision does the protocol make based on this data? (pricing, liquidation threshold, reward rate, rebase trigger, collateral valuation, etc.)
**Hardcoded stablecoin pricing**: Does the protocol skip oracle lookup for any asset and hardcode its price (e.g., USDC = 1e8)? All assets require dynamic oracle pricing — stablecoins depeg.
For each oracle identified in Step 1:
| Oracle | Timestamp Checked? | Max Staleness Enforced? | Staleness Threshold | Appropriate? | |--------|-------------------|------------------------|--------------------:|-------------| | {name} | YES/NO | YES/NO | {seconds or NONE} | {analysis} |
**Pyth-specific**: Is `price.publish_time` compared against `timestamp::now_seconds()`? What max age is enforced? **Switchboard-specific**: Is the aggregator's `latest_confirmed_round.round_open_timestamp` validated?
**Chained feed deviation**: If derived prices require multiple feeds (e.g., token_A/USD via token_A/APT + APT/USD), sum individual deviation thresholds to compute total worst-case deviation. If total exceeds LTV buffer → FINDING.
**If NO staleness check**: What happens when the oracle returns stale data?
For each consumer function, trace the impact of receiving data that is {freshness_guarantee x 2} old:
| Consumer Function | Data Used | If Stale By {X}: Impact | Severity | |-------------------|-----------|------------------------|----------| | {function} | {price/rate} | {specific impact} | {H/M/L} |
| Check | Code Reference | Status | |-------|---------------|--------| | `get_price()` or `get_price_no_older_than()` used? | {location} | {which} | | `price.publish_time` freshness validated? | {location} | YES/NO | | `price.price` (I64) sign checked (> 0)? | {location} | YES/NO | | `price.conf` confidence interval checked? | {location} | YES/NO | | `price.expo` (negative exponent) handled correctly? | {location} | YES/NO | | Price feed ID hardcoded or configurable? | {location} | {which} |
| Check | Code Reference | Status | |-------|---------------|--------| | Aggregator authority validated? | {location} | YES/NO | | Result staleness checked? | {location} | YES/NO | | Min/max response thresholds enforced? | {location} | YES/NO | | Aggregator config (min oracle results, variance threshold) appropriate? | {location} | YES/NO |
For each oracle data flow:
| Oracle | Oracle Decimals/Exponent | Consumer Expects | Normalization Applied? | Correct? | |--------|------------------------|-----------------|----------------------|----------| | {name} | {expo or scale} | {expected by math} | YES/NO | {analysis} |
**Pyth decimal handling**: Pyth uses `expo` field (typically negative, e.g., `expo = -8` means 8 decimal places). The actual price = `price.price * 10^expo`. Common errors:
**Switchboard decimal handling**: Uses `mantissa` and `scale` (or `decimals`). Actual value = `mantissa * 10^(-scale)`.
**MANDATORY GREP**: Search all oracle consumer files for hardcoded decimal constants: `100000000`, `1e8`, `10_000_000`, `DECIMAL`, `PRECISION`. For each hit: (1) Is this a decimal normalization constant? (2) Does it match the ACTUAL oracle's decimal format? (3) If the oracle feed changes or is swapped, does this constant break?
**Decimal chain trace**: For each arithmetic operation using oracle data, trace the full decimal chain: `oracle_output_decimals` -> `normalization_step` -> `consumer_expected_decimals`. If any step uses a hardcoded constant rather than reading decimals dynamically -> FINDING.
**Common decimal mismatches on Aptos**:
Autonomous Web3 security auditor for Claude Code and OpenAI Codex CLI. Orchestrates 18-100 AI agents across 40+ phases to produce audit reports with verified PoC exploits — for smart contracts and L1 node-client infrastructure.
Repo: PlamenTSV/plamen
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth…
Trigger Pattern Always (Aptos Move) - Move VM aborts on shift = bit width - Inject Into…
Trigger Protocol has privileged roles (admin, operator, governance, resource account owner) -…
Trigger EXTERNAL_LIB flag detected (protocol uses third-party Move dependencies) - Used by…
Trigger Pattern MONETARY_PARAMETER flag (required) - Inject Into Breadth agents (merged via…