feat(dolomite-plugin): initial release v0.1.0 — Arbitrum lending/borrowing#41
Conversation
📋 Phase 3: AI Code Review Report — Score: N/A/100
❌ 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: 1083760 bytes, plugin content: 170392 bytes. Generated by Claude AI via Anthropic API — review the full report before approving. |
🔨 Phase 2: Build Verification — ✅ PASSED
Build succeeded. Compiled artifact uploaded as workflow artifact. Source integrity: commit SHA `` is the content fingerprint. |
🔨 Phase 2: Build Verification — ❌ FAILED
Build failed. Check the workflow logs. Source integrity: commit SHA `` is the content fingerprint. |
✅ Phase 1: Structure Validation — PASSED→ Proceeding to Phase 2: Build Verification |
Phase 3 local AI review findings (PR mig-pre#41): 1. .claude-plugin/plugin.json description had 1 em-dash (U+2014). skill-md-maintenance-guide §0.7 mandates ASCII for plugin.json (CI lint.rs:946 panics on em-dash). Replace with '-'. 2. 21 hardcoded function selectors in src/rpc.rs::selectors with zero runtime verification (Dolomite uses Account.Info struct args, encoded as (address,uint256) in ABI signatures, which is the trickiest shape to get right by hand). A typo would silently misroute calls. Add rpc::tests::selectors_match_keccak256 covering all 21 selectors: - 5 ERC-20 (balanceOf/allowance/approve/decimals/symbol) - 6 DolomiteMargin writes (depositWei, withdrawWei, openBorrowPosition, closeBorrowPosition, transferBetweenAccounts, repayAllForBorrowPosition) - 7 simple-arg reads (getNumMarkets, getMarketTokenAddress, etc.) - 3 Account.Info struct reads (getAccountWei, getAccountStatus, getAccountValues) -- struct encoding verified Required adding sha3 + hex as dev-dependencies (not runtime deps, keeps the binary lean). Pattern matches euler-v2 / aave-v2 / compound-v2 / fourmeme. Also added '.ai-review/' to '.gitignore' so locally-generated Phase 3 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>
…owing
Dolomite Finance integration on Arbitrum (chain id 42161) — supply assets to
earn interest, open isolated borrow positions with up to 32 collaterals each,
repay debt cleanly via Dolomite's native exact-debt sentinel, and withdraw,
all via the DolomiteMargin core + DepositWithdrawalProxy + BorrowPositionProxyV2.
Commands (7):
- quickstart: scans 8 well-known markets (USDC/USDT/WETH/DAI/WBTC/ARB/USDC.e/LINK),
returns 6-state status enum + ready-to-run next_command
- markets: per-market live supply/borrow APYs + utilization
- positions: per-account snapshot (supply + borrow + USD-equiv); --account-number
for isolated positions
- supply: depositWei to main or isolated account
- withdraw: withdrawWei to wallet (--from-account-number for isolated)
- borrow: two-tx flow on BorrowPositionProxyV2 (openBorrowPosition →
transferBetweenAccounts) — main account 0 cannot go negative, real
borrowing requires isolated accounts. --collateral-amount 0 skips step 1
- repay: dust-free --all via repayAllForBorrowPosition (Dolomite's
exact-debt sentinel, analog of Aave V3 type(uint256).max). Three-branch
decision tree (A: main supply ≥ debt single-tx; B: main short → top-up
+ repayAll; C: insufficient → INSUFFICIENT_BALANCE). Settles to exactly 0,
addressing LEND-001
Selectors verified directly against on-chain bytecode:
- DepositWithdrawalProxy 0xAdB9D68c613df4AA363B42161E1282117C7B9594:
depositWei(u,u,u) 0xfe491ee7 / withdrawWei(u,u,u,u8) 0xc38fd74e
- BorrowPositionProxyV2 0x38E49A617305101216eC6306e3a18065D14Bf3a7:
openBorrowPosition 0xbb0a6fa5 / transferBetweenAccounts 0x58e8cf03 /
repayAllForBorrowPosition 0xb0463d5c / closeBorrowPosition 0x8fb8b6c7
Knowledge base compliance: GEN-001 / ONB-001 / ONC-001 / EVM-001 / EVM-002 /
EVM-006 / EVM-014 (3-pattern allowance-lag retry) / EVM-015 (60k approve,
400-450k writes) / TX-001 (wait_for_tx + on_chain_status field) / GAS-001 /
LEND-001 (exact-zero dust guarantee).
End-to-end verified on Arbitrum mainnet: supply USDC + USDT, open isolated
position 100 with 0.3 USDC collateral, borrow 0.2 USDT (real debt creation
via transferBetweenAccounts), repay --all to exact zero (tx 0xca8aa1…9777,
on-chain debt = 0 atom), withdraw collateral back to wallet.
v0.1.0 scope: Arbitrum-only. Berachain / Polygon zkEVM / X Layer / Mantle
deferred to v0.2.0 (pending onchainos wallet support).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…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>
…tter + SUMMARY.md Phase 1 lint reads SKILL.md frontmatter (panicked on em-dash in description). SUMMARY.md may also be processed; conservatively strip all non-ASCII: em-dash, en-dash, >= and <= unicode → ASCII equivalents. plugin.yaml was already fixed in 1073158. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1 lint may process the full SKILL.md, not just frontmatter. Conservatively strip remaining non-ASCII: em-dash (41x), ellipsis, >=, arrows, x. ASCII equivalents preserve readability for human + agent consumers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1 lint [E106] requires user confirmation language nearby any 'wallet contract-call' mention in SKILL.md. Expanded supply Flow step 5 + ONC-001 compliance row to explicitly note --confirm gating. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… section This compliance table was a self-imposed addition not required by any maintenance rule and not present in any other plugin (verified across all 25 SKILL.md files in the repo). It was internal-jargon for code reviewers that doesn't belong in user-facing SKILL.md, and the 'wallet contract-call' mention in the table caused E106 to fire repeatedly. Removing the section removes the lint trigger AND aligns with community structure (Pre-flight / Commands / Errors / Routing / Security Notice). The one user-relevant nugget (LEND-001 dust-free repay-all) was already documented in the repay command section, so no info loss. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tion 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>
Phase 3 local AI review findings (PR mig-pre#41): 1. .claude-plugin/plugin.json description had 1 em-dash (U+2014). skill-md-maintenance-guide §0.7 mandates ASCII for plugin.json (CI lint.rs:946 panics on em-dash). Replace with '-'. 2. 21 hardcoded function selectors in src/rpc.rs::selectors with zero runtime verification (Dolomite uses Account.Info struct args, encoded as (address,uint256) in ABI signatures, which is the trickiest shape to get right by hand). A typo would silently misroute calls. Add rpc::tests::selectors_match_keccak256 covering all 21 selectors: - 5 ERC-20 (balanceOf/allowance/approve/decimals/symbol) - 6 DolomiteMargin writes (depositWei, withdrawWei, openBorrowPosition, closeBorrowPosition, transferBetweenAccounts, repayAllForBorrowPosition) - 7 simple-arg reads (getNumMarkets, getMarketTokenAddress, etc.) - 3 Account.Info struct reads (getAccountWei, getAccountStatus, getAccountValues) -- struct encoding verified Required adding sha3 + hex as dev-dependencies (not runtime deps, keeps the binary lean). Pattern matches euler-v2 / aave-v2 / compound-v2 / fourmeme. Also added '.ai-review/' to '.gitignore' so locally-generated Phase 3 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>
…pattern) Same as compound-v2: §0.6 forbids exposing internal knowledge-base rule codes in SKILL.md. External agents do not have the KB and cannot resolve what 'LEND-001' means. Removed 2 occurrences of '**LEND-001**' from the repay --all command description and changelog entry. The prose around them already describes the dust-free settlement semantic; the code reference adds no value to a reader without the KB. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8824cba to
cdff796
Compare
✅ Phase 4: Publish CompletePlugins:
Published by Plugin Store CI |
Summary
Dolomite Finance integration on Arbitrum One. Decentralized money market + margin protocol with a unified action model — supports 1000+ assets and isolated borrow positions (up to 32 collaterals each).
7 commands (read:
quickstart/markets/positions; write:supply/withdraw/borrow/repay). All write commands require explicit--confirm. v0.1.0 = Arbitrum-only (other Dolomite chains pending onchainos wallet coverage).Highlights
AccountBalanceHelperforbids the main account (0) from going negative, so real borrowing must happen on a non-zero account.borrowruns a two-tx flow onBorrowPositionProxyV2:openBorrowPosition(0, N, …)to move collateral, thentransferBetweenAccounts(N, 0, …)to drain the borrow asset (creating debt on N).--collateral-amount 0skips step 1 to re-borrow against existing position collateral.repay --all— uses Dolomite's native exact-debt sentinelrepayAllForBorrowPosition(analog of Aave V3type(uint256).max). Three-branch decision tree: (A) main supply ≥ debt → 1 tx, no approve; (B) main short → top-up wallet→main + repayAll (2-3 tx); (C) insufficient →INSUFFICIENT_BALANCE. Settles to exactly zero, addressingLEND-001knowledge-base bug.depositWei/ 4-argwithdrawWei/ 6-argtransferBetweenAccountswere core-contractoperate-style signatures that don't exist on the user-facing proxies; replaced with the proxy's actual variants (3-arg, 4-arg, 5-arg) after bytecode scan.getMarketInterestRate, supply rate derived asborrow_rate × earnings_rate / 1e18, per-second compounded to APY.Knowledge base compliance
GEN-001 ✓ ONB-001 ✓ ONC-001 ✓ EVM-001 ✓ EVM-002 ✓ EVM-006 ✓ EVM-014 (3 patterns) ✓ EVM-015 (60k/400k/450k gas-limits) ✓ TX-001 ✓ GAS-001 ✓ LEND-001 ✓ (exact-zero guarantee)
Test plan
cargo buildclean (warnings only, no errors)--help↔ SKILL.md flag paritysupply --token USDC --amount 0.5→ tx0x7ca5fb…8ca9✓supply --token USDT --amount 1→ tx0x76bdf4…5725✓borrow --token USDT --amount 0.5 --collateral-token USDC --collateral-amount 0.3 --position-account-number 100→ step 10x3c4f25…fec6, step 20xeb5213…817f(real debt) ✓repay --token USDT --all --position-account-number 100→ tx0xca8aa1…9777, position 100 USDT balance verified0atom on chain ✓withdraw --token USDC --amount 0.300001 --from-account-number 100→ tx0xe6b9df…f255, position emptied ✓{ok:false, error_code, suggestion}JSON via stdout (GEN-001)🤖 Generated with Claude Code