Auditor DogSubmit a repository
Security audit report

lidofinance/solido

commit 81abead · claude-opus-4-5 · corpus auditor-skill@4.3 · 2026-06-20 00:00 UTC

0
Critical
0
High
0
Medium
0
Low
0
Info

Provenance

Visibility
public
Highest severity
none / 10
Report sha256
962d9b524879137dc5fe324f4765b53d02165ee5885473dc4c66522725aa23fd
Usage
0 in · 0 out · 0 cached · $0.00
Source file
frcd10/auditor-attest./reports/…
README badge
[![audit](https://auditor-attest.vercel.app      (troque pelo domínio que a Vercel te der)/badge/lidofinance/solido.svg)](https://auditor-attest.vercel.app      (troque pelo domínio que a Vercel te der)/r/lidofinance/solido)

On-chain attestation · Solana devnet

Transaction
afcnDPPByfSbzuDNyimN5TER8Lz2WL2z8KcHy5D5nibaZJoTHWsJ1VYNCp6PFUEs97UNM1nUufC4ZxdVZAqrHsf
Account
8Qqh7S5jLTou2vZqLbN3VYVAtWynRfRMu2f3CzRDg9ev
Attester
4ZwnFVFENrXwLjdxz8g835TSQq4J8cVByH45vXPDenQf
Program
sXtvdoheTtFBukx8vCppJHhiiJHW2xa3xc5KaPAhzkC

Verify without us: the account address is the PDA of sha256(lowercased repo url) + the commit bytes under the program; its data holds the report sha256 above.

Solido (Lido for Solana) — Program Security Audit

FieldValue
RepositoryLido/solido (Lido for Solana — liquid staking)
Scopeprogram/ (on-chain Solido staking program)
Primary programprogram/src/ — native Rust (no Anchor); entrypoint entrypoint.rs -> processor::process
Audit typeAI-assisted first-pass (manual code review)
Date2026-06-20
AuditorAutomated security review agent (Claude)

1. Executive Summary

This audit covered the on-chain Solido program: deposit/withdraw, the per-epoch stSOL/SOL exchange-rate accounting, stake/unstake delegation to validators, reward/fee minting, validator/maintainer administration, and the manual (native, non-Anchor) account/signer/owner/PDA validation.

Verdict: The core staking program is well-engineered and defensively coded. Account validation is centralized in a single accounts_struct! macro that enforces is_signer/is_writable flags and verifies fixed-address (sysvar/program) accounts on every instruction. All value-moving PDAs (reserve, stake/mint authority, per-validator stake/unstake accounts) are re-derived and compared before any CPI. Arithmetic uses checked wrapper types (Lamports/StLamports) with u128 intermediates; the exchange rate is fixed per-epoch (computed only by the permissionless UpdateExchangeRate), structurally neutralizing deposit/donation ordering and the classic first-depositor share-inflation vector. Admin actions are gated by check_manager, maintenance by check_maintainer; owner and token/mint checks are present throughout.

No confirmed vulnerabilities of severity ≥ 4. Items examined resolved to by-design behavior or pre-existing low-risk code-quality notes (§3). The codebase carries multiple prior professional audits (audit/). First-pass review; not a substitute for a full professional audit with runtime testing.

Repository Risk Score: 0 / 10 (Minimal — no confirmed findings)

Severity Distribution (Confirmed Findings Only)

SeverityCount
Critical (9-10)0
High (7-8)0
Medium (4-6)0
Low (1-3)0
Total0

2. Confirmed Findings

None. No issue reached the confidence/severity bar (≥4, substantiated from code). Highest-value paths examined and found sound:

  • Exchange-rate & share accounting (state.rs ExchangeRate::exchange_sol/exchange_st_sol, 411-448): multiply-then-divide in u128 (token.rs:106-118), 1:1 fallback when supply/balance zero, rounding favors the pool.
  • Deposit (processor.rs:180-227): SOL transferred to reserve before stSOL minted; mint identity, mint-authority PDA, recipient account validity checked in mint_st_sol_to (logic.rs:200-243).
  • Withdraw (processor.rs:1034-1174): requires current exchange rate, forces withdrawal from most-staked validator, re-derives source_stake_account, burns stSOL with token-owner check, enforces min stake-account balance.
  • Reward/fee minting (logic.rs:343-399): gated on mint + fee-recipient identities + up-to-date rate; reward derived from observed-vs-tracked balances via observe_balance.
  • Stake/unstake (processor.rs:229-595): maintainer-gated; PDAs re-derived/balance-checked; merge accounts epoch-scoped.
  • Manual validation: accounts_struct! enforces signer/writable + const-address equality; check_account_owner/deserialize_lido enforce ownership and type discriminants.

3. Investigated but Not Confirmed (by-design / low-confidence / refuted)

  • Deposit uses per-epoch-stale exchange rate — by design (documented in state.rs:327-393; rate fixed for epoch so deposits/donations commute). No theft path.
  • First-depositor / vault-donation inflation — by design (rate is a stored snapshot updated only by permissionless UpdateExchangeRate; 1:1 fallback when supply zero; donations socialized at next update).
  • Dust-rounding loss on small deposits — low-confidence/accepted (rounds down, harms only dust-depositor; favors pool).
  • get_vote_account_commission reads byte 68 with only owner check in perf-update path — low-confidence, no fund-loss (bounds-safe .get(68); instructions adjust perf flags only).
  • Permissionless UpdateStakeAccountBalance .expect() on subtraction — refuted (observe_balance errors cleanly before; no slashing on Solana; defensive only).
  • Deprecated Pubkey::new — informational, correct behavior.
  • Admin/manager trust model — by design (manager is a multisig per multisig/).