fix(lido-plugin): sync to okx v0.2.8 + biz-type/strategy attribution + 1 EVM-012 (v0.2.9)#76
Conversation
…+ 1 EVM-012 (v0.2.9)
This PR brings mig-pre/main lido-plugin from v0.2.7 to v0.2.9. The bulk
of the diff is the v0.2.7 → v0.2.8 sync (already on okx/main), with our
biz-type/strategy attribution + 1 EVM-012 safety-gate fix layered on top.
== Sync portion (mig-pre v0.2.7 → okx v0.2.8) ==
17 files changed. These are the v0.2.8 changes already living on
okx/main that mig-pre is missing. They include:
- New `quickstart` command (commands/quickstart.rs)
- get_withdrawals refactor + main.rs registration
- Stake / unwrap / wrap / request_withdrawal tweaks (already reviewed
on okx side)
== New in v0.2.9 ==
Add `--biz-type dapp --strategy lido-plugin` to every onchainos
`wallet contract-call` invocation. Source-of-truth for the strategy
name is Cargo.toml's `[package].name` via `env!("CARGO_PKG_NAME")` —
no drift between Cargo.toml, plugin.yaml, plugin.json.
Affected onchainos call sites (7):
- commands/stake.rs (ETH → stETH stake)
- commands/wrap.rs × 2 (stETH approve + wrap to wstETH)
- commands/unwrap.rs (wstETH → stETH unwrap)
- commands/request_withdrawal.rs × 2 (stETH approve + queue withdrawal)
- commands/claim_withdrawal.rs (claim finalized withdrawal)
Also fix one real EVM-012 (silent decode error swallowing) found by
the Step 1.5 scan:
- commands/stake.rs:48 — `decode_uint256(...).unwrap_or(0)` on the
`isStakingPaused()` pre-flight check. Decode failure was treated as
"val=0" = "not paused" and let staking proceed even when the actual
contract state was unknown. This is a *safety gate*, not a display
field — silent fallback means a paused-contract stake could pass
through. Changed to explicit `?` propagation with a clear anyhow
error message naming which RPC step failed.
Other `unwrap_or(0)` sites scanned and classified:
- onchainos.rs (block num display + native_balance hex parse) —
display fallbacks after explicit RPC error branch upstream
- claim_withdrawal.rs / get_withdrawals.rs (boolean flag decoding from
well-known WithdrawalQueue ABI) — soft fallback acceptable
- quickstart.rs — display only
EVM-006 sleep at onchainos.rs is the receipt-confirmation poll
(correct pattern, not a race condition).
Version bump: mig-pre v0.2.7 → v0.2.9 (PATCH — backwards-compatible).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🔨 Phase 2: Build Verification — ✅ PASSED
Build succeeded. Compiled artifact uploaded as workflow artifact. Source integrity: commit SHA `` is the content fingerprint. |
📋 Phase 3: AI Code Review Report — Score: 89/100
1. Plugin Overview
Summary: Rust-based plugin that wraps the Lido liquid staking protocol on Ethereum mainnet. Provides stake / balance / withdrawal-request / claim / wrap / unwrap operations against the stETH, wstETH, and WithdrawalQueueERC721 contracts via Target Users: Ethereum users who want to stake ETH on Lido through an agent-driven CLI flow without leaving the OKX onchainos environment. 2. Architecture AnalysisComponents: skill (SKILL.md + SUMMARY.md) + Rust binary ( Skill Structure: SKILL.md includes auto-injected pre-flight (skipped from review), Overview, Architecture, Pre-flight Checks, Quickstart, Contract Addresses, ~9 commands with parameter tables and ABI calldata details, Error Handling, Suggested Follow-ups, Skill Routing, Security Notices. Roughly 9 user-facing commands. Data Flow:
Dependencies: clap, tokio, reqwest, serde, serde_json, anyhow, hex. External services: ethereum.publicnode.com, yields.llama.fi, wq-api.lido.fi. 3. Auto-Detected Permissionsonchainos Commands Used
All commands are present in the onchainos CLI source provided. Wallet Operations
External APIs / URLs
Chains Operated OnEthereum mainnet only (chain ID 1), per Overall Permission SummaryThis plugin can read wallet ETH/stETH/wstETH balances and submit signed Ethereum transactions (stake, approve, wrap/unwrap, withdrawal request, claim) through onchainos's TEE-signed wallet pipeline. All signing happens through onchainos — the plugin never holds private keys. Outbound network calls go to three pinned domains (DeFiLlama, Lido WQ-API, publicnode RPC); no untrusted user input is interpolated into URLs. Calldata is constructed locally in Rust, which is auditable and avoids prompt injection of transaction parameters. 4. onchainos API ComplianceDoes this plugin use onchainos CLI for all on-chain write operations?Yes. On-Chain Write Operations (MUST use onchainos)
Data Queries (allowed to use external sources)
External APIs / Libraries Detectedreqwest (HTTPS client), tokio (async runtime). No web3/ethers libraries used for signing — calldata is hand-rolled and signing is delegated. Verdict: ✅ Fully Compliant5. Security AssessmentStatic Rule Scan (C01-C09, H01-H09, M01-M08, L01-L02)
No other static rules match. No LLM Judge Analysis (L-PINJ, L-MALI, L-MEMA, L-IINJ, L-AEXE, L-FINA, L-FISO)
Toxic Flow Detection (TF001-TF006)No toxic flows detected. No combination of (curl|sh + financial) (TF005), no (sensitive-path + network) (TF001), no (prompt-injection + persistence) (TF002), no (unverifiable-dep + malicious-intent) (TF004), no (missing-boundary + financial) (TF006 — boundary declaration is present). Prompt Injection ScanNo instruction override, identity manipulation, hidden behavior, confirmation bypass instructions, or hidden content (no base64 blobs, no invisible characters). Result: ✅ Clean Dangerous Operations CheckPlugin involves transfers, contract calls, and broadcasting transactions. The SKILL.md and the Rust source enforce explicit Result: ✅ Safe Data Exfiltration RiskExternal calls go to three pinned domains for known-public data (APY, wait time, RPC reads). No environment variables, no Result: ✅ No Risk Overall Security Rating: 🟢 Low Risk6. Source Code Security (if source code is included)Language & Build ConfigRust, entry point Dependency Analysisclap (CLI parsing), tokio (async), reqwest (HTTP with rustls + native-tls), serde / serde_json (JSON), anyhow (error handling), hex (encoding). All are mainstream, actively maintained crates. No suspicious or unmaintained packages. Code Safety Audit
Subprocess invocation in ABI calldata construction in Amount conversion uses Does SKILL.md accurately describe what the source code does?Yes. SKILL.md command list, parameters, calldata structures (selectors Verdict: ✅ Source Safe7. Code ReviewQuality Score: 89/100
Strengths
Issues Found
8. Language Check
9. SUMMARY.md Review
11. Recommendations
12. Reviewer SummaryOne-line verdict: Well-structured, security-conscious Lido staking plugin that correctly delegates all signing to onchainos and includes proper confirmation gating, balance pre-flights, and untrusted-data boundary declarations. Merge recommendation: ✅ Ready to merge Blockers (if any — list every issue that MUST be fixed before merge, each prefixed with ❌): No blockers found. Non-blocking improvements listed in Recommendations are all polish items that can be addressed in a future patch release. 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. |
mig-pre CI Phase 1 [E151] enforces '## Quick Start' as a required section. okx/main has been renaming this section to '## How it Works' in newer plugins, but mig-pre's lint hasn't been updated to accept that. Until the lint diverges or okx reverts, keep mig-pre's standard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✅ Phase 4: Publish CompletePlugins:
Published by Plugin Store CI |
Summary
This PR brings mig-pre/main lido-plugin from v0.2.7 → v0.2.9 in one shot, since mig-pre was 1 version behind okx/main when we picked up the work.
The diff is 2 logical parts:
Part 1: Sync mig-pre v0.2.7 → okx/main v0.2.8 (17 files)
These changes already live on okx/main and have been reviewed/merged there. They include:
quickstartcommand (commands/quickstart.rs)Part 2: New in v0.2.9 — biz-type/strategy attribution + 1 EVM-012 fix
Attribution (src/onchainos.rs)
Injected into the args of
wallet_contract_call. Covers 7 call sites:env!("CARGO_PKG_NAME")keeps strategy name in sync with Cargo.toml — no drift across the 4 metadata files.EVM-012 fix (src/commands/stake.rs:48)
isStakingPaused()pre-flight haddecode_uint256(...).unwrap_or(0). On decode failure that returnedval=0= "not paused" and let staking proceed even when contract state was unknown. This is a safety gate, not a display field — silent fallback could let a paused-contract stake through. Changed to explicit?propagation with named error.Audit notes
Other
unwrap_or(0)sites classified as not EVM-012:onchainos.rsblock num display + native_balance hex parse (display fallbacks after explicit RPC error branch upstream)claim_withdrawal.rs/get_withdrawals.rsboolean ABI flag decoding (soft fallback acceptable for well-known WithdrawalQueue contract)quickstart.rsdisplay onlyEVM-006 sleep is the receipt-confirmation poll (correct pattern).
Test plan
cargo buildpasses🤖 Generated with Claude Code