agents/skills/evm/migration-analysis/SKILL.md
Trigger Protocol has migration patterns (reinitializer, V2/V3, deprecated, upgrade, legacy) - Covers Token type mismatches, stranded assets, interface incompatibilities
npx skillsauth add plamentsv/plamen migration-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Trigger: Protocol has migration patterns (reinitializer, V2/V3, deprecated, upgrade, legacy) Covers: Token type mismatches, stranded assets, interface incompatibilities
reinitializer|V2|V3|_deprecated|migrat|upgrade|legacy|oldToken|newToken
Find all token migration patterns:
For each transition: | Old Token | New Token | Migration Function | Bidirectional? |
For each external call that involves migrated tokens:
// Example mismatch:
interface IExternalProtocol {
function deposit(address asset, uint256 amount) external returns (uint256);
// Expects: canonical token
// Actually returns: receipt token denominated in bridged variant?
}
For each function that interacts with migrated tokens:
| Function | User Provides | Protocol Tracks | External Expects | Mismatch? |
When migration changes token types or interaction patterns, check whether external call side effects produce tokens that the current logic handles correctly.
For each external call that returns tokens or triggers side effects:
| External Call | Pre-Migration Side Effect | Post-Migration Side Effect | Logic Handles Both? | Mismatch? | |---------------|--------------------------|---------------------------|---------------------|-----------| | {ext_call} | Returns Token A | Returns Token B (or same token, different accounting) | YES/NO | {describe} |
Pattern: Migration changes the primary token (e.g., V1 -> V2), but external contracts still return the old token as rewards, receipts, or side effects. The new logic may not handle the old token type.
Check: For each external dependency, does the post-migration logic correctly handle ALL token types that external calls can produce -- including legacy types from pre-migration interactions still in flight?
Before analyzing stranded asset paths, inventory what the contract CURRENTLY HOLDS:
| Asset Type | How It Arrived | Current Balance Query | Post-Upgrade Logic Handles? | Exit Path Post-Upgrade? |
|------------|---------------|----------------------|----------------------------|------------------------|
| {token_A} | User deposits | tokenA.balanceOf(this) | YES/NO | {function or NONE} |
| {token_B} | External rewards | Claimed via {ext_call} | YES/NO | {function or NONE} |
| {token_C} | Legacy operations | Held from V1 interactions | YES/NO | {function or NONE} |
Pattern: Upgrade changes which token the protocol uses (V1 -> V2), but the contract still holds V1 tokens from pre-upgrade operations. If the new logic only handles V2, V1 balances are stranded.
Check: For every asset type the contract can hold pre-upgrade:
CRITICAL: This step uses exhaustive methodology to ensure no stranded asset scenarios are missed. Every sub-step is MANDATORY.
List ALL assets the protocol handles, categorized by migration era:
| Asset | V1 Entry Path | V2 Entry Path | V1 Exit Path | V2 Exit Path | |-------|---------------|---------------|--------------|--------------| | Token A | deposit_v1() | deposit() | withdraw_v1() | withdraw() | | Token B | stake_v1() | stake() | unstake_v1() | unstake() |
Rule: If V1 Entry exists but V2 Exit doesn't handle V1 state -> potential stranding
For EACH asset and EACH possible state combination:
| Asset Era | State Condition | Available Exit Paths | Works? | Reason | |-----------|-----------------|---------------------|--------|--------| | V1 deposit | V2 logic active | withdraw() | Y/N | {why} | | V1 deposit | V1 logic deprecated | withdraw_v1() | Y/N | {why} | | V1 deposit | In-flight during upgrade | ??? | Y/N | {why} |
STRANDING RULE: If ALL exit paths = N for any state -> STRANDED ASSETS FINDING
Document ALL functions that could recover stranded assets:
| Function | Who Can Call | What Assets Can Recover | Limitations | |----------|--------------|------------------------|-------------| | emergencyWithdraw() | Admin only | All tokens | Requires admin action | | migrate() | Anyone | V1 balances | One-time only | | sweep() | Admin only | Unaccounted tokens | Cannot recover user deposits |
Question: Is there a recovery path for EVERY stranding scenario in 4b?
Model these specific scenarios with code traces:
Scenario 1: V1 Deposit + V2 Logic
State: User deposited 100 tokens via V1 deposit()
Event: Protocol upgraded to V2
Question: Can user withdraw via V2 withdraw()?
Trace: [document code path]
Result: [SUCCESS/STRANDED + amount]
Scenario 2: In-Flight During Upgrade
State: User initiated withdrawal at V1 block N
Event: Upgrade happened at block N+1
Question: Can user complete withdrawal at block N+2?
Trace: [document code path]
Result: [SUCCESS/STRANDED + amount]
Scenario 3: External Token Type Mismatch
State: Protocol received TokenA from external contract
Event: External contract now returns TokenB
Question: Can protocol process/withdraw TokenA?
Trace: [document code path]
Result: [SUCCESS/STRANDED + amount]
Step Execution Output: checkmark4a,4b,4c,4d,4e or ?4X(incomplete reason)
For each external call:
| External Contract | Function | Protocol Sends | Contract Expects | Match? |
|-------------------|----------|----------------|------------------|--------|
| ExternalPool | deposit | depositAsset | depositAsset | YES |
| ExternalPool | withdraw | receiptTokens | receiptTokens | YES |
| PriceOracle | getPrice | - | Returns USD or ETH? | VERIFY |
Check whether user actions can create state that prevents admin migration or management operations:
| Admin/Migration Function | Precondition Required | User Action That Blocks It | Timing Window | Severity | |--------------------------|----------------------|---------------------------|---------------|----------| | {admin_func} | {precondition} | {user_action creating conflicting state} | {window size} | {assess} |
Pattern: Admin migration or management functions require certain state conditions (e.g., "no pending operations", "all users migrated", "no active requests"). Users performing normal operations (withdrawals, deposits, claims) may create state that blocks these admin functions.
Check for each admin/migration function:
If blocking is possible AND permanent -> minimum MEDIUM severity If blocking is temporary but repeatable -> assess with Rule 10 worst-state
When the protocol changes token types, interfaces, or behavior during migration, check how downstream consumers are affected:
| Protocol Change | Downstream Consumer Type | Expected Interface/Token | Actual Post-Migration | Breaking Change? | |-----------------|--------------------------|--------------------------|----------------------|-----------------| | {what changed} | DeFi integrations (lending, DEX) | {expected} | {actual} | YES/NO | | {what changed} | Indexers/subgraphs | {expected events/signatures} | {actual} | YES/NO | | {what changed} | Frontend/UI | {expected token type} | {actual} | YES/NO | | {what changed} | Other protocol contracts | {expected interface} | {actual} | YES/NO |
Pattern: Protocol migrates from TokenV1 to TokenV2, but downstream integrators (other protocols, composability layers, frontends) still expect TokenV1 behavior. This creates silent failures or incorrect accounting in the integration layer.
Check:
For each finding:
## Finding [MG-N]: Title
**Verdict**: CONFIRMED / PARTIAL / REFUTED / CONTESTED
**Step Execution**: checkmark1,2,3,4,5 | xN(reason) | ?N(uncertain)
**Severity**: Critical/High/Medium/Low/Info
**Location**: Contract.sol:LineN
**Token Transition**:
- Old: {old_token}
- New: {new_token}
- Mismatch Point: {where types diverge}
**Description**: What's wrong
**Impact**: What can happen (stranded funds, wrong accounting, DoS)
**Evidence**: Code showing mismatch
### Precondition Analysis (if PARTIAL/REFUTED)
**Missing Precondition**: [What blocks exploitation]
**Precondition Type**: STATE / ACCESS / TIMING / EXTERNAL / BALANCE
### Postcondition Analysis (if CONFIRMED/PARTIAL)
**Postconditions Created**: [What conditions this creates]
**Postcondition Types**: [List applicable types]
After completing analysis, verify:
If any step skipped, document valid reason (N/A, single token, no external deps, no downstream consumers).
development
Prepare Solidity projects for a security audit — test coverage, test quality, NatSpec docs, code hygiene, dependency health, best-practice enforcement, deployment readiness, and project documentation checks. Generates a scored Audit Readiness Report and optionally runs static analysis. Trigger on: "prepare for audit", "audit readiness", "pre-audit check", "audit prep", "NatSpec check", or any request to review a Solidity codebase before a security review.
development
Launch the Plamen deterministic Web3 security audit pipeline
development
Run the Plamen smart-contract audit wizard in Codex
testing
Launch the Plamen deterministic L1 infrastructure audit pipeline