Skip to content

feature: V3Provider#151

Open
razww wants to merge 21 commits into
masterfrom
feature/v3-lp
Open

feature: V3Provider#151
razww wants to merge 21 commits into
masterfrom
feature/v3-lp

Conversation

@razww

@razww razww commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

A Lista V3 concentrated-liquidity collateral provider for the slisBNB/BNB pair, used as Moolah collateral. The original monolith exceeded EIP-170, so it is split into three UUPS contracts with clean boundaries, plus a dedicated liquidator:

  • V3Provider / SlisBNBV3Provider — ERC-4626 vLP shares that are the Moolah collateral token. Owns share accounting + Moolah wiring; holds no NFT. The slisBNB subclass adds slisBNBx reward mirroring, per-user deposit tracking, and the BOT-gated rebalance entry.
  • V3DexAdapter / SlisBNBV3DexAdapter — the sole V3 NFT + idle-inventory custodian and all NPM/pool math. The slisBNB subclass adds the exchange-rate-implied fair price, ±1% auto-centered range, and the rate-centered rebalance + StakeManager inventory conversion.
  • SlisBNBV3ProviderOracle — the Moolah market.oracle. Prices the share off the adapter's manipulation-resistant fair composition + the resilient oracle, with a capped haircut.
  • V3Liquidator — liquidator for V3-provider-backed markets: pre-funded liquidation, flash liquidation with callback share-redemption + DEX swap, and standalone share/token ops.

Architecture (3-contract split)

Contract One job Holds
V3Provider (vault) ERC-4626 shares, Moolah supply/withdraw, share accounting, CEI shares
V3DexAdapter (strategy) NFT custody, all NPM/pool writes, raw-NAV/composition views the V3 NFT + idle inventory
SlisBNBV3ProviderOracle (oracle) price the share for Moolah (fair view + haircut) nothing

The vault never touches the NFT/pool; the adapter never imports Moolah or the share token (it takes (shares, totalShares) as opaque fractions); the oracle reads only public views. Raw-NAV vs haircut is cleanly separated (adapter returns raw, oracle applies the only haircut).

Key Design Decisions

  • slisBNB/BNB only. The adapter and oracle constructors reject any non-slisBNB/WBNB pair (NotSlisBnbWbnbPair); the oracle additionally asserts its tokens match the adapter's (AdapterPairMismatch), so a mis-wired deploy can't silently misprice.
  • Exchange-rate oracle (not TWAP). The fair price is StakeManager-implied (convertSnBnbToBnb), not pool spot/TWAP — peek/totalAssets/getUserBalanceInBnb are invariant to pool-price manipulation. Per-leg USD comes from the resilient oracle; peek reverts on a zero leg price or zero total value (finding D); supply == 0 returns 0
    (pre-market).
  • Value-based shares. shares = addedValue × supplyBefore / totalValueBefore, valuing freshly-added liquidity at the fair price (first deposit denominated in the accounting asset, WBNB). Fees are compounded before minting so existing holders capture them before dilution.
  • Rate-centered rebalance. Recenters to the exchange-rate ±1% range, converts free inventory to the optimal ratio via the StakeManager (deposit/instantWithdraw, measured by balance delta — not pool-manipulable), guarded by a configurable rate-drift threshold (centerRateThresholdBps) + deadline + minLiquidity. BOT-gated on the vault;
    onlyProvider on the adapter.
  • Deposit-refund reentrancy fix (C-1). The unused-input refund is forwarded to the depositor after _mint + supplyCollateral (CEI), so the native-BNB refund callback can't observe an inflated share price (stale totalSupply vs. already-added NAV) and reenter Moolah.borrow. Withdraw/redeem likewise burn before the adapter pushes
    underlying to the receiver.
  • Idle-inventory tracking via idleToken0/idleToken1 storage (not balanceOf) so donations can't inflate NAV.
  • Native BNB support — deposits accept msg.value (auto-wrapped to WBNB); withdrawals unwrap WBNB to native BNB.
  • AccessControlEnumerableUpgradeable across vault/adapter/oracle/liquidator (codebase standard; enumerable roles).
  • IV3PoolMinimal slot0 read — decodes only sqrtPriceX96/tick, width-agnostic to feeProtocol (Uniswap uint8 vs PancakeSwap uint32), so the adapter works against any V3 fork.
  • V3 math sourced from the audited lista-dao-contracts libs; interfaces from the lista-v3 submodule.

Files

File Description
src/provider/V3Provider.sol Generic vault base — ERC-4626 shares + Moolah wiring + CEI
src/provider/SlisBNBV3Provider.sol slisBNB vault — slisBNBx mirror, deposit tracking, BOT rebalance
src/provider/V3DexAdapter.sol Generic DEX custodian — NFT + all NPM/pool math + raw-NAV views
src/provider/SlisBNBV3DexAdapter.sol slisBNB adapter — rate fair price, ±1% centering, rebalance + inventory conversion
src/provider/SlisBNBV3ProviderOracle.sol Moolah market.oracle — share pricing off fair view + haircut
src/provider/interfaces/*.sol IV3Provider, IV3DexAdapter, ISlisBNBV3DexAdapter, IV3ProviderOracle, IV3PoolMinimal, IStakeManager
src/provider/libraries/V3PositionLib.sol NPM mint/increase/decrease/collect/burn primitives
src/provider/libraries/SlisBnbInventoryLib.sol StakeManager inventory conversion (delegatecall lib)
src/liquidator/V3Liquidator.sol Liquidator: pre-funded + flash liquidation, share redemption, DEX swaps
test/provider/SlisBNBV3Provider.t.sol Functional suite (slisBNB/WBNB fork, block 60541406)
test/provider/SlisBNBV3ProviderRate.t.sol Rate-path invariance + rebalance
test/provider/V3ProviderReentrancyPoC.t.sol C-1 deposit-refund reentrancy regression
test/liquidator/V3Liquidator.t.sol Liquidator fork tests

Test Plan

All suites fork BSC mainnet at block 60541406 (slisBNB/WBNB 1bp pool; the live StakeManager is etched with a faithful instantWithdraw stand-in for the rebalance conversion).

  • Functional (SlisBNBV3Provider.t.sol) — deposit/withdraw/redeem/supplyShares/withdrawShares, value-based share math, previews, oracle peek/getTokenConfig + finding-D, one-sided & slippage guards, transfer restrictions, slisBNBx integration, rebalance (incl. out-of-range via inventory conversion), borrow/repay/liquidate.
  • Rate-path (SlisBNBV3ProviderRate.t.sol) — peek/totalAssets/getUserBalanceInBnb invariant to pool manipulation; rate-centered rebalance + drift/deadline/minLiquidity guards. (8 tests)
  • Liquidator (V3Liquidator.t.sol) — pre-funded + flash liquidation, share redemption, token/BNB swaps, whitelist/access control. (27 tests)
  • Reentrancy PoC (V3ProviderReentrancyPoC.t.sol) — test_C1_depositRefundReentrancy_neutralized drives the full attack; fails pre-fix (≈26× inflation, insolvent), passes post-fix.
  • Manual: deploy to testnet, verify deposit/withdraw/rebalance/liquidation end-to-end against a real Lista V3 slisBNB/BNB pool.
forge test --mc SlisBNBV3ProviderTest -vvv
forge test --mc SlisBNBV3ProviderRateTest -vvv
forge test --mc V3LiquidatorTest -vvv
forge test --mc V3ProviderReentrancyPoC -vvv

@razww razww marked this pull request as draft March 23, 2026 13:20
Comment thread src/provider/V3Provider.sol Outdated
@razww razww marked this pull request as ready for review March 27, 2026 06:39
raz-w-20230331 and others added 2 commits April 2, 2026 15:28
… fork

Remove scattered LICENSE files under dex/v3/core/ and add a single NOTICE
file with proper attribution. Transition expired BUSL-1.1 headers to
GPL-2.0-or-later and fix GPL-3.0 incompatibility in periphery libraries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the ~9.4k-LoC local fork under src/dex/v3 (a Uniswap-v3 fork
ported to 0.8.34) and depend on github.com/lista-dao/lista-v3 instead.

lista-v3 master is Solidity 0.7.6, so it cannot be compiled into this
0.8.34 codebase wholesale. Split by what actually compiles under 0.8.34:

- Pure interfaces (IListaV3Factory, IListaV3Pool, pragma >=0.5.0) now
  come from the lib/lista-v3 submodule via the `lista-v3/` remapping.
- The V3 math libs V3Provider executes internally (TickMath, SqrtPriceMath,
  LiquidityAmounts, FullMath, FixedPoint96, SafeCast, UnsafeMath) are
  0.7.6 upstream and need 0.8.x unchecked semantics, so the existing
  0.8.34 ports are relocated to src/provider/libraries/.
- INonfungiblePositionManager: the submodule's interface inherits OZ
  ERC721-upgradeable interfaces whose v4-era paths/names don't exist in
  this repo's OZ v5.2, so a minimal self-contained NPM interface (only
  the methods V3Provider calls) lives in src/provider/interfaces/.

Delete test/dex/v3/ListaV3.t.sol (tested the fork implementation itself;
the DEX is tested in the lista-v3 repo) and repoint the IListaV3Pool
import in V3Provider/V3Liquidator tests to the submodule.

The unrelated StableSwap DEX under src/dex/*.sol is untouched.
forge build: compiler run successful.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
razww and others added 2 commits June 8, 2026 13:10
Replace the 7 locally-vendored 0.8.34 math-lib ports under
src/provider/libraries/ with the audited, 0.8-native libraries from the
lista-dao-contracts submodule (pinned at 3ac9ef2, matching master).

- Register lib/lista-dao-contracts.git as a submodule + `lista-dao-contracts/`
  remapping. The entry mirrors origin/master exactly, so it is conflict-free
  when this branch later integrates with master.
- V3Provider imports TickMath and LiquidityAmounts from the submodule.
- _getAmountsForLiquidity now delegates to LiquidityAmounts.getAmountsForLiquidity,
  which is mathematically identical to the previous SqrtPriceMath.getAmount{0,1}Delta
  (roundUp=false) path. This removes the need for SqrtPriceMath (which
  lista-dao-contracts does not ship a 0.8 version of) and its deps.
- Delete all 7 local ports: TickMath, SqrtPriceMath, LiquidityAmounts, FullMath,
  FixedPoint96, SafeCast, UnsafeMath.

Verified: forge build clean; 84 V3Provider + 27 V3Liquidator tests pass
(covering preview/withdraw/rebalance across below/inside/above-range, which
exercises the swapped getAmountsForLiquidity path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve conflicts in .gitmodules and remappings.txt by unioning both sides:
- .gitmodules: keep our lib/lista-v3 submodule alongside master's existing
  lib/lista-dao-contracts.git entry.
- remappings.txt: keep our lista-v3/ and lista-dao-contracts/ remappings
  plus master's lista-dao-contracts.git OZ-upgradeable remappings.

forge build clean; 84 V3Provider tests pass on the merged tree.
@flow-saas flow-saas Bot removed the needs-rebase label Jun 8, 2026
razww and others added 7 commits June 9, 2026 10:03
…-rate oracle

Rename V3Provider → SlisBNBV3Provider and split into a generic abstract base
(V3Provider) + slisBNB/BNB specialization, per the slisBNB/BNB v3 LP PRD.

- Base/derived split via virtual hooks (_afterCollateralChange,
  _rebalanceInventory, _valuationSqrtPriceX96, peek/getTokenConfig/receive).
- ERC-4626 shell: asset = WBNB, totalAssets() in BNB; single-asset entry
  disabled (two-token deposit/withdraw/redeemShares + withdrawShares/supplyShares).
- Exchange-rate oracle (PRD §4.5): peek/totalAssets/getUserBalanceInBnb value the
  position at the slisBNB exchange-rate-implied price (StakeManager
  convertSnBnbToBnb/convertBnbToSnBnb), never the pool spot/TWAP — manipulation-resistant.
- Auto-centered range: initialize derives ticks from exchangeRate ±1%; rebalance
  recenters and converts inventory via the StakeManager (deposit / instantWithdraw).
- Libraries: V3PositionLib (NPM primitives) + SlisBnbInventoryLib (stake/redeem +
  optimal-ratio conversion); audited 0.8 math from lista-dao-contracts.
- require strings → custom errors; AccessControl (non-enumerable).
- Tests: SlisBNBV3Provider.t.sol (USDC/WBNB generic) + SlisBNBV3ProviderRate.t.sol
  (slisBNB/WBNB rate-path, forked).

Note: runtime bytecode currently exceeds EIP-170; size-reduction refactor pending.

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

Split the monolithic SlisBNBV3Provider (28.5 KB, over EIP-170) into three UUPS
contracts, each well under the limit, with clean responsibility boundaries:

- V3Provider / SlisBNBV3Provider: ERC-4626 vLP shares + Moolah wiring + share
  accounting (holds no NFT); slisBNB subclass adds slisBNBx mirroring + BOT rebalance.
- V3DexAdapter / SlisBNBV3DexAdapter: sole V3 NFT/idle custodian + all NPM/pool math;
  slisBNB subclass adds the exchange-rate-implied fair price, +/-1% tick centering,
  and the rate-centered rebalance + StakeManager inventory conversion.
- SlisBNBV3ProviderOracle: Moolah market.oracle; prices the share off the adapter's
  fair composition (manipulation-resistant) + resilient oracle, capped haircut.

Key points:
- CEI: burn shares BEFORE adapter.removeLiquidity pushes underlying to the receiver,
  so totalSupply stays consistent with the reduced position during the BNB callback.
- Oracle reverts on zero leg price / zero total value (finding D); raw-NAV vs haircut
  split is clean (adapter returns raw, oracle applies the only haircut).
- slisBNB/BNB-only: adapter and oracle constructors reject any non-slisBNB/WBNB pair;
  the oracle also asserts its tokens match the adapter's (no wiring divergence).
- IV3PoolMinimal: decode only slot0 sqrtPriceX96/tick, width-agnostic to feeProtocol
  (Uniswap uint8 vs PancakeSwap uint32) so the adapter works against any V3 fork.
- Tests retargeted to the slisBNB/WBNB pool: functional 87, rate-path 8, liquidator 27
  (etched StakeManager stand-in for the not-yet-deployed instantWithdraw).

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

- foundry.lock: remove orphaned lib/v3-core and lib/v3-periphery entries
  (superseded by lista-v3; no .gitmodules entry, lib dir, remapping, or import).
- Apply prettier formatting to the V3 vault/adapter contracts and the
  liquidator + rate-path tests (npm run check now passes).

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

Switch V3Provider, V3DexAdapter and SlisBNBV3ProviderOracle from plain
AccessControlUpgradeable to AccessControlEnumerableUpgradeable, matching the
codebase standard (Moolah, SmartProvider, et al.) so roles are enumerable
on-chain via getRoleMember/getRoleMemberCount. Existing role logic
(grantRole/hasRole/onlyRole/getRoleAdmin) is unchanged; all three stay under EIP-170.

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

Match the V3 provider contracts and the codebase standard so roles are
enumerable on-chain (getRoleMember/getRoleMemberCount). Existing role logic is
unchanged; V3Liquidator stays well under EIP-170.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
V3Provider.deposit forwarded the unused-input refund to the depositor via a
native-BNB call inside adapter.addLiquidity, BEFORE _mint + supplyCollateral.
During that callback the adapter NAV already included the freshly-added
liquidity while totalSupply() was still stale, so SlisBNBV3ProviderOracle.peek
returned a transiently inflated share price (26x on a BSC fork). Moolah was not
yet reentrancy-locked at that point, letting a malicious depositor reenter
Moolah.borrow and over-borrow against pre-existing collateral, leaving bad debt.

Fix: the adapter now refunds to the vault, and the vault forwards the refund to
the depositor only AFTER _mint + supplyCollateral, when NAV and totalSupply are
consistent. Adds a guarded receive() (adapter-only) + _refund helper.

Regression: test_C1_depositRefundReentrancy_neutralized drives the full attack
and asserts peek during the refund equals the normal price and the attacker
position stays solvent. Fails pre-fix (26x inflation, insolvent), passes post-fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…reentrancy

fix(provider): close deposit-refund reentrancy (C-1)
@razww

razww commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

@audit-agent V3Liquidator.sol V3DexAdapter.sol V3Provider.sol SlisBNBV3DexAdapter.sol SlisBNBV3Provider.sol SlisBNBV3ProviderOracle.sol SlisBnbInventoryLib.sol V3PositionLib.sol

@lista-audit-agent

Copy link
Copy Markdown

🛡️ Cloud-Auditor — PR #151 review

Dispatched: 9 specialists · Head SHA: b48933fd

Tally

Critical High Medium Low Info
0 2 5 9 19

Top findings

H-01 — slisBNBxMinter.rebalance revert bricks deposit / withdraw / liquidation   SlisBNBV3Provider.sol:116-127
V3Provider.liquidate (Moolah callback) → _afterCollateralChange_syncPositionminter.rebalance reverts EXCEED_MPC_CAP when MPC wallets are full. The Moolah liquidation reverts; unhealthy positions cannot be cleared. Inherits PR-188 M-01 without the recommended try/catch. Fix: wrap minter call in try/catch, emit SyncFailed.

H-02 — getUserBalanceInBnb div-by-zero on bnbPrice cascades to full DoS   SlisBNBV3Provider.sol:88
(value0+value1)/bnbPrice with no zero-guard. When slisBNBxMinter is wired, a transient BNB feed dip panics through every deposit/withdraw/liquidate via _syncPosition → minter.rebalance → getUserBalanceInBnb. Sibling code already uses the defensive return 0 pattern. Fix: if (bnbPrice == 0) return 0;.

M-01 — setSlisBNBxMinter does not verify provider-is-registered   SlisBNBV3Provider.sol:106-109
Same as PR-188 M-02. Rotating to a minter that hasn't pre-registered V3Provider bricks every _syncPosition thereafter. Fix: assert moduleConfig(address(this)).moduleAddress == address(this) in the setter.

M-02 — Resilient-oracle TOKEN0/TOKEN1 legs must be rate-derived for the pool-manipulation invariant to hold
Composition is rate-based (manipulation-resistant) but per-token USD prices come from resilientOracle. A DEX-based slisBNB feed re-opens the inflation vector closed by bailsec smart_provider Issue_07. Deploy runbook requirement; optionally enforce on-chain.

M-03 — centerRateThresholdBps MANAGER misconfig can permanently block rebalance
Range 0..10000 BPS; slisBNB rate moves ~4%/yr. Any setting above ~200 BPS makes rebalance unreachable. Fix: cap at ~500 BPS.

M-04 — V3Liquidator.NoProfit checks balanceOf < repaidAssets, not delta
A pre-existing loanToken balance silently covers swap paths producing zero output — amplifies BOT-compromise blast radius. Fix: balance-delta check or sweep between liquidations.

M-05 — peek ZeroPrice revert bricks liquidation while either resilient-oracle leg is down (intentional; document, monitor heartbeats)

Lows (9)

L-01 Missing __gap in SlisBNBV3Provider, SlisBNBV3DexAdapter, V3Liquidator (PR-188 L-09 pattern) ·
L-02 SmartProvider.setSlisBNBxMinter zero-guard removed (regression) ·
L-03 V3DexAdapter.setProvider irreversible — wrong wiring traps NFT + idle ·
L-04 ERC-4626 max* not overridden (spec break, PR-188 M-01 secondary) ·
L-05 V3Provider.liquidate / syncUserBalance missing nonReentrant (defense-in-depth) ·
L-06 V3Liquidator.withdrawERC20/ETH lets MANAGER drain (acknowledged centralization) ·
L-07 _sqrtPriceX96FromRate(0) silently misprices when rate == 0 ·
L-08 Base V3DexAdapter.fairSqrtPriceX96 reverts when pool observationCardinality == 1 (deploy checklist) ·
L-09 WBNB-refund call reverts for non-payable receivers (document).

Acknowledged / verified safe

  • C-1 deposit-refund reentrancy fix verified (PoC + call-graph trace).
  • First-depositor / donation inflation structurally blocked by storage-tracked idle accounting.
  • Pool spot manipulation of share price neutralized by StakeManager-rate fair sqrt price.
  • BOT trust on swap calldata: cites bailsec-lista_lending-2025-04-10 Issue_29 (acknowledged).
  • DEFAULT_ADMIN_ROLE renounce: cites cantina-credit_loan-2026-02-04 §3.3.2 (Timelock).

Full report (PDF) delivered to the security Telegram group.

razww and others added 2 commits June 26, 2026 09:40
…ETH/wbETH

Generalize the slisBNB V3 LP provider into a chain/LST-agnostic base and add
Ethereum wstETH/WETH and wbETH/WETH markets.

- Base: chain/LST-agnostic V3Provider / V3DexAdapter / V3ProviderOracle
  (WRAPPED_NATIVE immutable; virtual _lstNativeRate() / _convertToOptimalRatio()
  hooks). slisBNB becomes a thin, byte-equivalent subclass. All V3 contracts
  relocated under src/provider/v3/.
- New LST families: wstETH/WETH and wbETH/WETH adapters + vaults + IWstETH/IWbETH.
- Oracle: rate-implied (slisBNB) / pool-TWAP-clamped-to-rate (wstETH/wbETH) share
  pricing; components valued rate-derived via the resilient oracle.
- Rebalance swap is DEX-agnostic: backend-built swapData against a whitelisted
  swapPair (SwapInventoryLib generic swap, backend amountOutMin); drop SwapRouter02
  coupling (delete ISwapRouter02).
- V3Liquidator: chain-agnostic native leg via provider.WRAPPED_NATIVE() for both
  legs; wrap native back when loanToken == wrapped-native; reject sensitive
  swapPair (token/pool/NPM).
- Cross-validate provider<->adapter<->oracle wiring in setProvider + oracle ctor.

Tests: 245 passing — BSC slisBNB/liquidator regression unchanged + Ethereum fork
suites for wstETH, wbETH and V3Liquidator (incl. native-leg + wiring guards).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…onversion

Add maxInstantWithdrawSlippageBps to SlisBnbInventoryLib so the slisBNB→BNB
instantWithdraw leg of a rebalance enforces a bound on the StakeManager
instant-redeem fee/slippage, reverting InstantWithdrawSlippage when exceeded.
Threaded through convertToOptimalRatio/convert/_convert; SlisBNBV3DexAdapter
passes the configured bound. Adds tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hashdit-bot

hashdit-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

Pull Request Review

This PR introduces a new V3 collateral-provider architecture for concentrated liquidity positions by adding multiple new Solidity contracts: a generic V3Provider vault, V3DexAdapter strategy/custody layer, standalone V3ProviderOracle, chain/pair-specific variants (slisBNB, wstETH, wbETH), and a new V3Liquidator. It also updates build configuration/remappings and adds extensive fork-based tests for BSC and Ethereum covering deposits/withdrawals, rebalancing, liquidation paths, and reentrancy regression behavior. Additionally, there is a small change in SmartProvider.setSlisBNBxMinter validation logic (zero address check replaced by same minter check).

Sensitive Content

Blockchain Address:

  • 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE (native token sentinel) in src/liquidator/V3Liquidator.sol, src/provider/v3/SlisBNBV3Provider.sol, tests
  • 0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B (slisBNB) in src/provider/v3/SlisBNBV3DexAdapter.sol, src/provider/v3/SlisBNBV3ProviderOracle.sol, tests
  • 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c (WBNB) in src/provider/v3/SlisBNBV3DexAdapter.sol, src/provider/v3/SlisBNBV3ProviderOracle.sol, tests
  • 0x1adB950d8bB3dA4bE104211D5AB038628e477fE6 (StakeManager) in src/provider/v3/SlisBNBV3DexAdapter.sol, tests
  • 0xa2E3356610840701BDf5611a53974510Ae27E2e1 (wbETH) in src/provider/v3/WbETHV3DexAdapter.sol
  • 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH) in src/provider/v3/WbETHV3DexAdapter.sol, src/provider/v3/WstETHV3DexAdapter.sol
  • 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 (wstETH) in src/provider/v3/WstETHV3DexAdapter.sol

Security Issues

🟡 [MEDIUM] Input validation relaxed in setSlisBNBxMinter (confirm intended behavior)

File: src/provider/SmartProvider.sol
The setter changed from rejecting zero address (require(_slisBNBxMinter != address(0), ...)) to only rejecting setting the same value. This now allows setting slisBNBxMinter to address(0), which alters prior access/operational assumptions and may disable rebalancing hook integrations unexpectedly if not intentional.
Recommendation: Confirm this is intended as a feature (explicit disable path). If yes, consider documenting it clearly and emitting a distinct event/guardrail for disabling; if not, restore the non-zero check.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

@hashdit-bot

hashdit-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

Pull Request Review

This PR introduces a new V3 concentrated-liquidity provider architecture for slisBNB/WBNB by adding multiple new Solidity components: V3Provider (vault), V3DexAdapter (NFT/pool custodian), SlisBNBV3ProviderOracle (share oracle), and V3Liquidator (liquidation flows), along with supporting interfaces/libraries and extensive fork-based tests. It also updates project dependencies/remappings to include lista-v3 and shared lista-dao-contracts libs. Additionally, SmartProvider.setSlisBNBxMinter was changed to allow zero-address unsetting while preventing no-op updates (same minter).

Sensitive Content

Blockchain Address:

  • 0xbb4C...095c (BSC WBNB) in multiple production files (e.g., src/provider/V3Provider.sol, src/provider/V3DexAdapter.sol, src/liquidator/V3Liquidator.sol) — hardcoded chain token constant
  • 0xB0b8...4A1B (slisBNB) in multiple production files (e.g., src/provider/SlisBNBV3DexAdapter.sol, src/provider/SlisBNBV3ProviderOracle.sol) — hardcoded pair token constant
  • 0x1adB...7fE6 (StakeManager) in src/provider/SlisBNBV3DexAdapter.sol — hardcoded external protocol dependency
  • 0xEeee...EEeE (native BNB sentinel address) in src/provider/SlisBNBV3Provider.sol and src/liquidator/V3Liquidator.sol — native token placeholder-style runtime constant

Security Issues

No serious security issues detected.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

@hashdit-bot

hashdit-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

Pull Request Review

This PR introduces a major new Solidity web3 architecture for V3 concentrated-liquidity collateral: a split between V3Provider (vault/share token), V3DexAdapter (NFT + pool custody/logic), and V3ProviderOracle, plus a new V3Liquidator for pre-funded and flash liquidation flows. It adds slisBNB/BSC and wstETH/wbETH Ethereum specializations, new inventory/position libraries, and extensive fork-based tests for providers, rate invariance, liquidator behavior, and reentrancy regression. It also updates project dependencies/remappings (including lista-v3) and adjusts one existing SmartProvider minter setter check.

Sensitive Content

Blockchain Address:

  • 0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B in src/provider/v3/SlisBNBV3DexAdapter.sol — hardcoded slisBNB token constant
  • 0x1adB950d8bB3dA4bE104211D5AB038628e477fE6 in src/provider/v3/SlisBNBV3DexAdapter.sol — hardcoded StakeManager constant
  • 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c in src/provider/v3/SlisBNBV3DexAdapter.sol — hardcoded WBNB constant
  • 0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B in src/provider/v3/SlisBNBV3ProviderOracle.sol — hardcoded slisBNB pair guard
  • 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c in src/provider/v3/SlisBNBV3ProviderOracle.sol — hardcoded WBNB pair guard
  • 0xa2E3356610840701BDf5611a53974510Ae27E2e1 in src/provider/v3/WbETHV3DexAdapter.sol — hardcoded wbETH constant
  • 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 in src/provider/v3/WbETHV3DexAdapter.sol — hardcoded WETH constant
  • 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 in src/provider/v3/WstETHV3DexAdapter.sol — hardcoded wstETH constant
  • 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 in src/provider/v3/WstETHV3DexAdapter.sol — hardcoded WETH constant

No sensitive key material or social account handles/links detected in non-test added files.

Security Issues

No serious security issues detected.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

razww and others added 3 commits June 26, 2026 13:49
…nostic swap)

Make the slisBNB/BNB rebalance inventory conversion identical to the wstETH/WETH and
wbETH/WETH families: a backend-built swap against a whitelisted venue, swap-pair-agnostic on
chain. instantWithdraw is conceptually just a swap, so the StakeManager special-casing is no
longer needed — promoting one shared implementation also simplifies the code.

- Promote the generic conversion to the base V3DexAdapter: swapPairWhitelist +
  setSwapPairWhitelist (rejecting TOKEN0/TOKEN1/POOL/NPM) + the decode-and-swap
  _convertToOptimalRatio (via SwapInventoryLib, backend amountOutMin). All three rate-implied
  subclasses inherit it; both declared on IV3DexAdapter.
- SwapInventoryLib is native-aware: when a venue settles the wrapped-native leg as the native
  coin (e.g. a StakeManager instant-redeem → BNB), the received native is wrapped back into the
  wrapped-native ERC20 before amountOutMin is measured; receive() accepts native from a
  whitelisted venue. ⇒ instantWithdraw works as a whitelisted swap venue (slisBNB→BNB→WBNB),
  with no StakeManager special-casing on chain.
- Slim SlisBNBV3DexAdapter to _lstNativeRate() (StakeManager rate) + the pair guard; drop the
  StakeManager conversion override, the instant-withdraw slippage config, and the StakeManager
  receive() override. Delete SlisBnbInventoryLib.
- Slim WstETH/WbETHV3DexAdapter: swap logic now in the base; keep rate hook + TWAP-clamp.
- SlisBNBV3Provider.rebalance gains bytes calldata swapData, forwarded to the adapter.

Behavioral change: slisBNB rebalance converts via a whitelisted venue (a DEX/aggregator OR the
StakeManager instant-redeem) using backend swapData + amountOutMin, instead of a hardcoded path.

Tests: 257 passing — slisBNB swap-conversion (instantWithdraw-as-venue, both directions,
amountOutMin-revert) + whitelist + sensitive-pair-reject; old StakeManager-special-case/slippage
tests removed; wstETH/wbETH/liquidator/reentrancy green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build on the unified DEX-agnostic rebalance swap (9ba9766) so the V3 LP base is correct for
native-settling venues and non-18-decimal tokens.

- SwapInventoryLib native-aware both directions: the swapData blob gains bool nativeIn — now
  (swapPair, sellToken0, amountIn, amountOutMin, nativeIn, innerSwapData). nativeIn ⇒ the wrapped-native
  input leg is unwrapped and forwarded as msg.value (supports StakeManager.deposit{value} for
  WBNB→slisBNB). Any native a venue delivers (e.g. instantWithdraw → BNB) is wrapped back into the
  wrapped-native ERC20 before amountOutMin is measured — never stranded; reverts UnexpectedNative if
  neither leg is the wrapped-native.
- Non-18-decimal paired token: _sqrtPriceX96FromRate now scales the raw pool price by
  10^(DECIMALS1 - DECIMALS0) instead of assuming equal decimals (pure→view; cascaded to _tickRangeForRate).
  The wrapped-native stays 18-dec; the paired token may have any decimals.
- Oracle share-decimal correctness: V3ProviderOracle quotes peek(share) per ONE WHOLE share
  (10 ** SHARE_DECIMALS, read from the share token) instead of hardcoded 1e18, matching Moolah._getPrice
  which uses collateralToken.decimals(). No-op for the current 18-dec accounting assets.

Tests: 263 passing — new V3DexAdapterDecimals.t.sol (non-18-dec USDC(6)/WETH(18) + 18/18) proves the
sqrtPrice decimal math; slisBNB depositAsSwapVenue (nativeIn), wrongNativeOutput_reverts, instantWithdraw
no-stranded-native; swapData blobs updated to the 6-field shape. Backend encoder must add nativeIn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
refactor(provider): unify slisBNB rebalance with wstETH/wbETH (DEX-ag…
@hashdit-bot

hashdit-bot Bot commented Jun 26, 2026

Copy link
Copy Markdown

Pull Request Review

This PR introduces a new V3 concentrated-liquidity provider architecture for Moolah collateral by adding a large set of Solidity contracts: V3Provider (vault shares + Moolah wiring), V3DexAdapter (sole NFT/liquidity custodian), V3ProviderOracle (share pricing), plus chain/pair specializations for slisBNB, wstETH, and wbETH, and a new V3Liquidator. It also updates project dependencies/remappings (including lista-v3) and adds extensive fork-based integration/regression tests across BSC and Ethereum. Additionally, an existing check in SmartProvider.setSlisBNBxMinter was changed from a non-zero guard to a “not same as current” guard.

Sensitive Content

Blockchain Address:

  • 0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B in src/provider/v3/SlisBNBV3DexAdapter.sol / src/provider/v3/SlisBNBV3ProviderOracle.sol — hardcoded slisBNB token address
  • 0x1adB950d8bB3dA4bE104211D5AB038628e477fE6 in src/provider/v3/SlisBNBV3DexAdapter.sol — hardcoded StakeManager address
  • 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c in src/provider/v3/SlisBNBV3DexAdapter.sol / src/provider/v3/SlisBNBV3ProviderOracle.sol — hardcoded WBNB address
  • 0xa2E3356610840701BDf5611a53974510Ae27E2e1 in src/provider/v3/WbETHV3DexAdapter.sol — hardcoded wbETH address
  • 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 in src/provider/v3/WbETHV3DexAdapter.sol / src/provider/v3/WstETHV3DexAdapter.sol — hardcoded WETH address
  • 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 in src/provider/v3/WstETHV3DexAdapter.sol — hardcoded wstETH address
  • 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE in src/liquidator/V3Liquidator.sol and provider contracts — native-token sentinel address

Security Issues

🟡 [MEDIUM] Input validation relaxed in setSlisBNBxMinter may allow zero address assignment

File: src/provider/SmartProvider.sol
The function changed from require(_slisBNBxMinter != address(0), "zero address provided"); to require(_slisBNBxMinter != slisBNBxMinter, "same minter");, which now permits setting the minter to address(0). This may be intentional (to disable minter), but it is an access/authorization-related behavior change that could alter downstream assumptions and disable rebalancing hooks unexpectedly.
Recommendation: Please confirm this is intended. If zero should be disallowed, restore explicit non-zero validation; if zero is a supported “disable” state, document it clearly and emit/handle it consistently across dependent flows.


Generated by Hashdit Bot. This tool can absolutely NOT replace manual audits.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants