Skip to content

feat(compound-v2-plugin): initial release v0.1.0 — Compound V2 exit tool#42

Merged
plugin-store-bot[bot] merged 10 commits intomig-pre:mainfrom
GeoGu360:feat/compound-v2-plugin
Apr 30, 2026
Merged

feat(compound-v2-plugin): initial release v0.1.0 — Compound V2 exit tool#42
plugin-store-bot[bot] merged 10 commits intomig-pre:mainfrom
GeoGu360:feat/compound-v2-plugin

Conversation

@GeoGu360
Copy link
Copy Markdown
Owner

Summary

Compound V2 (cToken-based) money market integration on Ethereum mainnet, positioned as an EXIT tool for legacy positions.

⚠️ Wind-down disclosure

As of 2026, all 6 major V2 markets (cDAI / cUSDC / cUSDT / cETH / cWBTC2 / cCOMP) have governance-paused both new supply (mintGuardianPaused = true) and new borrow (borrowGuardianPaused = true). Compound team's active development is on V3 (Comet).

This plugin's pre-flight short-circuits supply/borrow with structured MARKET_PAUSED_USE_V3 / BORROW_PAUSED_USE_V3 errors, redirecting users to compound-v3-plugin:

$ compound-v2-plugin supply --token USDC --amount 100 --confirm
{
  "ok": false,
  "error_code": "MARKET_PAUSED_USE_V3",
  "suggestion": "Install compound-v3-plugin: `npx skills add okx/plugin-store --skill compound-v3-plugin`"
}

10 commands

  • Read: quickstart (6-state status enum) / markets / positions
  • Write (exit flows, fully functional): withdraw (redeemUnderlying) / repay (uint256.max sentinel for dust-free --all) / claim-comp
  • Write (governance-blocked, return V3 redirect): supply / borrow
  • Collateral mgmt: enter-markets / exit-market

Highlights

  • LEND-001 dust-free repay via Compound V2's native cToken.repayBorrow(uint256.max) sentinel — contract auto-caps to current debt at execution time. Single-tx, no decision-tree complexity (simpler than Dolomite's branching A/B/C since Compound's contract handles the cap internally).
  • cETH payable handlingmint() no-args + value=amount, repayBorrow no-approve + value=amount. Distinct from ERC-20 mint(uint256) / repayBorrow(uint256) paths.
  • Selectors verified on-chain — every selector via keccak256 + live eth_call smoke test. Critical bug caught in dev: initial guess for borrowGuardianPaused(address) (0x6d35bf91) was wrong; correct is 0x6d154ea5. Wrong selector silently reverted, which my fail-closed is_borrow_paused.unwrap_or(true) in write commands correctly trapped, but read-side displays were silently showing borrow_paused=false. Fixed; re-verified all 6 markets show borrow_paused=true post-fix.
  • Comptroller is a Unitroller proxy — bytecode scan technique that worked for Dolomite's BorrowPositionProxyV2 (direct impl) didn't work here since Comptroller delegates to implementation at 0xbafe01ff…b526. Switched to live eth_call probe + keccak256-only verification.

Knowledge base compliance

GEN-001 ✓ ONB-001 ✓ ONC-001 ✓ EVM-001 ✓ EVM-002 ✓ EVM-006 ✓ EVM-014 (3 patterns) ✓ EVM-015 (80k/280k/450k/200k+70k×N) ✓ TX-001 ✓ GAS-001 (0.005 ETH floor for L1 mainnet) ✓ LEND-001

Test plan

  • cargo build clean (warnings only — unused selector consts kept for reference)
  • All 10 commands --help ↔ SKILL.md flag parity
  • SUMMARY.md three-section (Overview / Prerequisites / Quick Start), 8 steps, status enum aligned src ↔ SKILL.md ↔ SUMMARY.md
  • LICENSE present (CI E041)
  • api_calls covers single https domain (ethereum-rpc.publicnode.com)
  • 4-file version consistency at 0.1.0 (plugin.yaml, SKILL.md frontmatter, Cargo.toml, .claude-plugin/plugin.json)
  • Live verified on Ethereum mainnet (wallet 0x87fb…1b90, no V2 history):
    • quickstartstatus: protocol_winddown, next_command: npx skills add ... --skill compound-v3-plugin
    • markets → 6 markets, all mint_paused=true && borrow_paused=true, real APRs (cUSDC 3.82%, cETH 1.74%) ✓
    • positionsposition_count: 0, comp_accrued: 0, assets_in: []
    • supply --token USDC --amount 1 --confirmMARKET_PAUSED_USE_V3
    • borrow --token DAI --amount 1 --confirmBORROW_PAUSED_USE_V3
    • withdraw --token DAI --amount 1 --confirmNO_SUPPLY
    • repay --token USDC --all --confirmNO_DEBT
    • claim-comp --dry-runcompAccrued: 0 displayed ✓
    • enter-markets --ctokens cDAI --dry-run → preview correct, currently_entered: []
    • exit-market --ctoken cDAI --confirmNOT_IN_MARKET
  • All errors return structured {ok:false, error_code, suggestion} JSON via stdout (GEN-001)

🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

📋 Phase 3: AI Code Review Report — Score: N/A/100

Plugin: compound-v2-plugin | Recommendation: 👤 Manual review required

🔗 Reviewed against latest onchainos source code (live from main branch) | Model: unavailable via Anthropic API | Cost: N/A

This is an advisory report. It does NOT block merging. Final decision is made by human reviewers.


AI review FAILED (HTTP 400): Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.. Request size: 1246219 bytes, plugin content: 178604 bytes.


Generated by Claude AI via Anthropic API — review the full report before approving.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

🔨 Phase 2: Build Verification — ✅ PASSED

Plugin: compound-v2-plugin | Language: rust
Source: @

Compiled from developer source code by our CI. Users install our build artifacts.

Build succeeded. Compiled artifact uploaded as workflow artifact.


Source integrity: commit SHA `` is the content fingerprint.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

🔨 Phase 2: Build Verification — ✅ PASSED

Plugin: compound-v2-plugin | Language: rust
Source: @

Compiled from developer source code by our CI. Users install our build artifacts.

Build succeeded. Compiled artifact uploaded as workflow artifact.


Source integrity: commit SHA `` is the content fingerprint.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 29, 2026

✅ Phase 1: Structure Validation — PASSED

Linting skills/compound-v2-plugin...

  ⚠️  [W046] tag 'cToken' should be lowercase alphanumeric with hyphens

✓ Plugin 'compound-v2-plugin' passed with 1 warning(s)

→ Proceeding to Phase 2: Build Verification

Amos and others added 10 commits April 29, 2026 17:21
Compound V2 (cToken-based) money market integration on Ethereum mainnet,
positioned as an EXIT tool for legacy positions. As of 2026, all 6 major
markets (cDAI / cUSDC / cUSDT / cETH / cWBTC2 / cCOMP) have governance-paused
new supply AND borrow (mintGuardianPaused = borrowGuardianPaused = true).
Compound team's active development is on V3 (Comet); this plugin's pre-flight
checks short-circuit supply/borrow with structured MARKET_PAUSED_USE_V3 /
BORROW_PAUSED_USE_V3 errors that explicitly redirect users to compound-v3-plugin.

Commands (10):
- quickstart: scans 6 cTokens for wallet/supply/borrow + accrued COMP, returns
  6-state status enum (rpc_degraded / protocol_winddown / has_supply_can_redeem
  / has_debt_can_repay / has_comp_accrued / insufficient_gas) with
  ready-to-run next_command
- markets: per-cToken APRs, TVL, utilization, pause flags
- positions: per-cToken supply + borrow + COMP accrued, account_liquidity,
  assets_in (entered as collateral)
- supply: pre-flight mint-paused check → V3 redirect; full mint(amount)
  flow (cETH payable mint() for native) preserved for future
- withdraw: cToken.redeemUnderlying(amount); --amount all redeems exact
  current supply
- borrow: pre-flight borrow-paused + getAccountLiquidity check → V3 redirect;
  auto enterMarkets + cToken.borrow flow preserved
- repay: --all uses uint256.max sentinel (Compound V2 native max-sentinel,
  contract caps to current debt) → exact-zero dust guarantee, addresses
  LEND-001. cETH payable repay path
- claim-comp: Comptroller.claimComp(holder, address[] cTokens); reports
  before/after COMP balance diff for actual claim amount
- enter-markets / exit-market: collateral set management

Selectors (all keccak-verified + on-chain eth_call tested):
  cToken (CErc20 / CEther):
    mint(uint256) 0xa0712d68 / mint() 0x1249c58b
    redeemUnderlying(uint256) 0x852a12e3 / redeem(uint256) 0xdb006a75
    borrow(uint256) 0xc5ebeaec / repayBorrow(uint256) 0x0e752702
    balanceOfUnderlying / borrowBalanceCurrent / supplyRatePerBlock /
    borrowRatePerBlock / exchangeRateStored / totalBorrows / underlying
  Comptroller (Unitroller proxy 0x3d9819…9c9Cd3B):
    enterMarkets 0xc2998238 / exitMarket 0xede4edd0
    claimComp(address, address[]) 0x1c3db2e0
    compAccrued / getAllMarkets / getAccountLiquidity / getAssetsIn / markets
    mintGuardianPaused 0x731f0c2b / borrowGuardianPaused 0x6d154ea5

Build-time selector bug caught: initial guess for borrowGuardianPaused
selector (0x6d35bf91) was wrong — actual is 0x6d154ea5. Wrong selector
silently reverted; my fail-closed unwrap_or(true) in supply/borrow correctly
trapped (refused write), but read-side is_borrow_paused.unwrap_or(false)
silently displayed 'false' across markets/quickstart. Fixed across rpc.rs;
re-verified all 6 markets show borrow_paused=true post-fix.

Knowledge base compliance: GEN-001 / ONB-001 / ONC-001 / EVM-001 / EVM-002
/ EVM-006 / EVM-014 (3-pattern allowance-lag retry) / EVM-015 (per-op
gas-limits: approve 80k, redeem/repay 280k, borrow 450k, claimComp 200k+70k×N)
/ TX-001 (wait_for_tx + on_chain_status field) / GAS-001 (0.005 ETH floor for
L1 mainnet) / LEND-001 (uint256.max repay sentinel — exact-zero dust,
single-tx, simpler than Dolomite's branching since Compound caps internally).

Verified end-to-end on Ethereum mainnet: read commands return real on-chain
APRs (cUSDC borrow 3.82%, cETH borrow 1.74%, cWBTC2 borrow 2.11%); pause
flags correctly show all 6 markets paused; supply/borrow correctly
short-circuit with V3 redirect; withdraw/repay/exit-market return correct
NO_SUPPLY/NO_DEBT/NOT_IN_MARKET errors on user with no V2 history.

v0.1.0 scope: Ethereum mainnet only. V2 was never deployed officially on other
chains (BSC/Polygon "V2" instances are non-official forks: Venus / CREAM).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ml description

CI Phase 1 lint panics on UTF-8 multi-byte chars in description due to
string slicing assuming char boundaries (src/submission/lint.rs:946).
Em-dash "—" (U+2014, 3-byte UTF-8) caused panic at byte index inside char.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI Phase 1 lint requires:
- schema_version: 1
- author: { name, github } struct (not bare string)
- category, license, components, build sections
- "binary:" stanza was a my-format invention not in spec

Aligned to dolomite-plugin's already-passing schema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ription

Phase 1 lint also reads SKILL.md frontmatter, not just plugin.yaml.
The earlier plugin.yaml em-dash fix wasn't enough — frontmatter description
contained another em-dash, panicking lint.rs:946:36.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same root cause as dolomite — Phase 1 lint reads SKILL.md frontmatter and
panics on multi-byte UTF-8 (lint.rs:946:36). Conservatively strip non-ASCII
across SKILL.md body too: arrows, x, warning sigil, ellipsis -> ASCII
equivalents.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lint

Phase 1 lint [E106] requires user confirmation language nearby any 'wallet
contract-call' mention in SKILL.md. Expanded ONC-001 row in compliance
table to explicitly note that all 7 write commands require --confirm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nce section

Same rationale as dolomite-plugin's removal: this compliance table is not
required by maintenance rules, doesn't appear in any of the 25 other plugins
in the repo, and its 'wallet contract-call' mention triggered E106 lint
failures. Aligning with hyperliquid-plugin's reference structure (per user
feedback): Pre-flight Dependencies / Trigger Phrases / Commands / Skill
Routing / Security Notice / Do NOT Use For / Changelog.

The user-relevant LEND-001 dust-free guarantee is already documented under
the repay command section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…section

Aligns with canonical SKILL.md template (skill-md-maintenance-guide.md §0.1):
'Data Trust Boundary' is the 2nd most common H2 section across 28 canonical
skills (18/28 = 64%). Promoting from inline blockquote -> top-level H2 to
match precedent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ance

Phase 3 local AI review findings:

1. .claude-plugin/plugin.json description had 1 em-dash (U+2014). The
   skill-md-maintenance-guide §0.7 mandates ASCII for plugin.json (CI
   lint.rs:946 panics on em-dash). Replace with '-'.

2. 34 hardcoded function selectors in src/rpc.rs::selectors with zero
   runtime verification. A typo would silently misroute calls on chain.
   Add rpc::tests::selectors_match_keccak256 that recomputes every
   selector via keccak256 over the canonical signature and asserts
   equality. All 34 currently match (verified). Required adding sha3 +
   hex as dev-dependencies (not runtime deps -- keeps the binary lean).

   Pattern matches the runtime-selector test added to euler-v2-plugin /
   aave-v2-plugin / fourmeme-plugin during their reviews.

Also added '.ai-review/' to '.gitignore' so locally-generated Phase 3
review artifacts don't leak into commits.

Tests: 0/0 -> 1/1.
ASCII compliance: 1 non-ASCII -> 0.
Static scan own-source findings: 0 -> 0 (no regressions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…i-pattern)

CLAUDE.md / skill-md-maintenance-guide §0.6 forbids exposing internal
knowledge-base rule codes (e.g. LEND-001, EVM-001, ONC-001) in SKILL.md
because external agents reading the doc do not have the knowledge base
and cannot resolve what the codes mean. The intent should live in
prose: 'this addresses dust-free repay' is useful; 'addresses
**LEND-001**' is internal jargon.

Removed 1 occurrence of '**LEND-001**' from the repay command section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@GeoGu360 GeoGu360 added the ci-approved Maintainer reviewed PR; allows Phase 1/2/3 CI to run label Apr 29, 2026
@GeoGu360 GeoGu360 added the approved-for-publish Triggers Phase 4: compile + publish + merge label Apr 30, 2026
@plugin-store-bot plugin-store-bot Bot merged commit 4061893 into mig-pre:main Apr 30, 2026
31 checks passed
@plugin-store-bot
Copy link
Copy Markdown

✅ Phase 4: Publish Complete

Plugins: compound-v2-plugin

  • ✅ Build: 9 architectures compiled
  • ✅ Release: GitHub Release created
  • ✅ Pre-flight: injected into SKILL.md
  • ✅ Registry: registry.json updated
  • ✅ Merged to main

View workflow run


Published by Plugin Store CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed approved-for-publish Triggers Phase 4: compile + publish + merge ci-approved Maintainer reviewed PR; allows Phase 1/2/3 CI to run new-plugin structure-validated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant