ability-analysis
Trigger Pattern Always (Aptos Move) - foundational security check - Inject Into Breadth…
Trigger Pattern contractimport! or contracttype detected - Inject Into Breadth agents, depth-external
$ npx -y skills add PlamenTSV/plamen --skill custom-type-safety --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/custom-type-safetyContext preview
The summary Claude sees to decide when to auto-load this skill.
Trigger Pattern contractimport! or contracttype detected - Inject Into Breadth agents, depth-external
name: "custom-type-safety" description: "Trigger Pattern contractimport! or contracttype detected - Inject Into Breadth agents, depth-external"
> **Trigger Pattern**: `contractimport!` or `#[contracttype]` detected in codebase > **Inject Into**: Breadth agents, depth-external > **Finding prefix**: `[CT-N]` > **Rules referenced**: R4, R8, R10
Soroban contracts interact with external contracts through generated client bindings (`contractimport!`) and pass structured data across boundaries using `#[contracttype]` types. Both mechanisms carry security-relevant assumptions about versioning, type stability, and deserialization behavior that must be verified.
For every `contractimport!` macro invocation, identify what is being imported and whether it is pinned:
| Import Target | File/Path or Wasm Hash | Version Pinned? | Pinning Method | Stable? | |--------------|----------------------|----------------|---------------|--------| | `contractimport!("{target}")` | `{resolved path or hash}` | YES/NO | Hash / Path / None | YES/NO |
**Pinning methods (strongest to weakest)**: 1. **WASM hash**: `contractimport!(file = "...", sha256 = "0xabc...")` — exact bytecode pinning, most secure 2. **Specific file path in repo**: deterministic if the file is version-controlled alongside the contract 3. **Dynamic path or URL**: fetched at build time, non-deterministic — flag as HIGH risk
**Checks**:
When values of `#[contracttype]` types cross contract boundaries via `invoke_contract`, the receiving contract must be able to deserialize them. Verify semantic meaning is preserved:
| Type | Crosses Boundary? | Sending Contract Version | Receiving Contract Version | Compatibility? | |------|------------------|------------------------|--------------------------|---------------| | `{StructName}` | YES/NO | `{version or hash}` | `{version or hash}` | YES/NO |
**Safety rules**:
**Type confusion risk**: A `#[contracttype]` enum variant that serializes to the same `ScVal` representation as a variant in a different enum is a type confusion vector. This is rare but check when two enums use identical variant names or when raw `Val` conversions are used.
An imported contract may have been upgraded since the `contractimport!` snapshot was taken. If the imported ABI has changed, calling the contract with the old-generated client will fail at runtime:
| Imported Contract | Import Snapshot Date / Hash | Currently Deployed Hash | ABI Drift? | Breaking Changes? | |------------------|-----------------------------|------------------------|-----------|-----------------| | `{contract name}` | `{date or hash from file}` | `{check stellar explorer or build_status}` | YES/NO/UNKNOWN | YES/NO/UNKNOWN |
**How to detect**: 1. Compare the WASM hash in the `contractimport!` statement against the currently deployed contract's WASM hash via the Stellar network 2. If hashes differ, inspect the changelog or diff the generated client bindings against the current contract interface 3. Flag any function signature changes: added required parameters, changed parameter types, removed functions
**Impact of stale imports**: Runtime deserialization errors (`InvalidAction` / `WasmError`) when calling functions whose signatures have changed. The contract compiles successfully but fails at runtime, potentially during critical operations.
`#[contracttype]` enums and structs must handle all serialization edge cases. Verify correct handling:
| Type | All Enum Variants Handled in Match? | Default/Fallback for Unknown Variants? | Deserialization Panic on Unknown? | |------|-------------------------------------|---------------------------------------|----------------------------------| | `{EnumName}` | YES/NO | YES/NO | YES/NO → FLAG if YES |
**Enum exhaustiveness**:
#[contracttype]
pub enum Status {
Active,
Paused,
Closed,
}
// SAFE: all variants covered
match status {
Status::Active => ...,
Status::Paused => ...,
Status::Closed => ...,
}
// RISKY: if a new variant is added to the external contract's Status,
// deserialization succeeds but the match panics
match status {
Status::Active => ...,
Status::Paused => ...,
// Missing: Status::Closed → panic at runtime
}**Struct field additions**: If an external contract's `#[contracttype]` struct gains new fields, the importing contract's deserialization will fail with a type mismatch unless it uses versioned types or handles extra fields gracefully.
**For each `#[contracttype]` enum used in deserialization**:
Direct `Val` conversions (e.g., `Val::from_val`, `TryFromVal`, raw `RawVal` casts) bypass the typed `#[contracttype]` system. These must be handled with explicit error checking:
| Locati
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…