Skip to content

feature: V3Provider - #151

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

feature: V3Provider#151
razww wants to merge 51 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 force-pushed the feature/v3-lp branch 2 times, most recently from 04e090b to 7d940c4 Compare March 26, 2026 09:09
@razww
razww marked this pull request as ready for review March 27, 2026 06:39
@razww
razww force-pushed the feature/v3-lp branch 2 times, most recently from 9ff43ab to e1759f8 Compare March 31, 2026 06:17
@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.

@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.

@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.

@hashdit-bot

hashdit-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

Pull Request Review

This Solidity DeFi PR introduces an upgradeable V3 concentrated-liquidity collateral system comprising ERC-4626 provider vaults, DEX/NFT adapters, share-price oracles, and a dedicated liquidation contract for BSC and Ethereum LST pairs. It also adds rate-centered rebalancing, native-token handling, manipulation-resistant valuation, extensive fork tests, and a small SmartProvider minter-validation change.

Sensitive Content

No sensitive content detected.

Security Issues

🟠 [HIGH] Pre-existing native reserves can satisfy wrapped-native flash-liquidation repayment

File: src/liquidator/V3Liquidator.sol
When the loan token is the wrapped-native token, onMoolahLiquidate wraps the contract’s entire native balance after snapshotting only its ERC-20 loan-token balance. Consequently, native ETH/BNB held before the liquidation is converted into WETH/WBNB and counted as proceeds from the current liquidation, allowing an unprofitable liquidation to pass the out >= repaidAssets check and consume unrelated reserves. This bypasses the delta-based reserve-protection logic already applied to ERC-20 balances.
Recommendation: Snapshot the native balance before redemption and wrap only the native amount produced during the current callback, or include the wrapped value of the pre-existing native balance in the initial baseline. Add a regression test with pre-funded native reserves and an otherwise insufficient wrapped-native liquidation.


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

raz-w-20230331 and others added 10 commits July 29, 2026 16:19
… 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>
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>
…-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>
razww and others added 14 commits July 29, 2026 16:22
_twapTick computed the cumulative-tick delta and its division under Solidity
0.8 checked math, deviating from Uniswap's OracleLibrary.consult, which was
compiled under <0.8 and relies on the int56 subtraction wrapping. A wrapped
tickCumulatives delta would therefore revert here instead of producing the
reference tick. Wrap the delta/division/modulo in an unchecked block to match
the reference. Behavior is unchanged for all realistic observations (the wrap
is astronomically far off); this only removes the spurious-revert deviation.
All TWAP-using suites pass (153 tests).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rebalance enforced its minLiquidity floor only against the newly-minted
liquidity, which can be satisfied by liquidity minted at a price manipulated
around the call (then sandwiched on the attacker's back-swap). rebalance now
takes a targetSqrtPriceX96 — the pool price the backend built the rebalance
against — and, after the swap and re-mint, requires the actual pool spot to be
within maxSpotDeviationBps of it, reverting with SpotDeviationTooHigh
otherwise. A pool moved off the BOT's expectation therefore reverts instead of
minting off-market liquidity. targetSqrtPriceX96 == 0 opts out (parity with the
other caller-supplied guards) and maxSpotDeviationBps == 0 disables the gate.

The new argument threads through IV3DexAdapter.rebalance, the adapter, the
provider _guardedRebalance wrapper, and the three provider BOT entrypoints
(slisBNB / wbETH / wstETH). Generalizes the existing spot-vs-fair comparison
into a reusable _priceWithinDeviation helper. Adds seven rebalance target-price
tests (opt-out, gate-disabled, low/high-side, band boundary, sandwich-with-fair
target, matching-target pass). All V3 suites pass (307 tests).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ap legs

SwapInventoryLib.swap wrapped any native-balance increase after the venue call
back into the wrapped-native token, and reverted (UnexpectedNative) when
neither swap leg was the wrapped-native token. A venue that forwards its native
balance (e.g. a router that sweeps stray native — seedable by an attacker with
a 1-wei donation) could therefore brick an ERC-20<->ERC-20 conversion on a pair
where neither token is the wrapped-native.

The re-wrap now runs only when a swap leg IS the wrapped-native token; when
neither is, any native that appears is an unsolicited donation outside this
swap's accounting and is left untouched rather than reverting. The legitimate
native-out (proceeds) and native-in (unspent refund) paths are unchanged, and
the nativeIn input guard still uses UnexpectedNative.

Live pairs (slisBNB/WBNB, wstETH/WETH) always include the wrapped-native leg,
so this only affects future non-native pairs; a delegatecall-harness test
exercises the neither-leg path (a stray-native donation no longer reverts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ation

- V3ProviderOracle.initialize now emits HaircutChanged(_haircutBps) so the
  initial haircut is observable from events alone.
- setHaircutBps returns early when the value is unchanged, avoiding a redundant
  storage write and a misleading no-op HaircutChanged event.
- SlisBNBV3DexAdapter: the constructor already pins TOKEN0 == slisBNB and
  TOKEN1 == WBNB, so the always-true _isSlisBnbWbnbPool guard and the dead
  branch in _poolPriceRate are removed; _lstNativeRate returns
  STAKE_MANAGER.convertSnBnbToBnb(1e18) directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…compound hardening

- Compound accrued fees before the Moolah health-check valuation in
  withdraw / withdrawShares / supplyShares, so the position is valued
  with fees folded in rather than transiently under-valued.
- Fail closed on a zero oracle leg: V3Provider._amountsValueUsd and
  SlisBNBV3Provider.getUserBalanceInBnb now revert OracleZero when any
  returned price is 0 (prevents a transient-zero feed silently burning a
  user's reward balance toward 0).
- transferFrom override now debits the granted allowance via
  _spendAllowance before moving shares, instead of transferring on an
  unbounded allowance.
- Compounded event now reports the amounts actually consumed by
  increaseLiquidity (used0/used1), not the raw pre-leftover inputs.
- Clamp the initial tick range to the usable [MIN_TICK, MAX_TICK] band
  after floor/ceil alignment.
- Short-circuit a pure no-op recenter (range unchanged and no swap,
  target, or min floors supplied) to an in-place compound, avoiding an
  unnecessary burn/mint cycle; guarded / swap paths still run in full.

Adds counter-tests for the allowance-checked transfer and the no-op
recenter boundary; updates the recenter tests to assert compound-in-place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
flashLiquidate hardcoded the amount0 / amount1 fields of the
V3Liquidation event to 0. The real redeemed amounts are only known
inside the onMoolahLiquidate callback (redeemShares' return values),
which runs during Moolah's liquidate call, so they never reached the
emit site.

Capture the redeemed leg amounts in the callback and pass them back to
flashLiquidate via appended (upgrade-safe) storage, zeroed before each
liquidate so a non-redeeming flash liquidation still reports 0.

Adds a counter-test asserting both event amounts are non-zero after a
redeem-and-swap flash liquidation.

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

- removeLiquidity reverts ZeroAmount when a share-burning redeem would
  deliver (0,0), instead of silently burning the caller's shares.
- SwapInventoryLib.swap fails fast with InsufficientInventory when the
  requested amountIn exceeds the position's balance, rather than silently
  capping (which desynced the venue allowance from swapData and could
  underflow the totals).
- V3ProviderOracle.peek floors a dust position's price to a non-zero unit
  instead of reverting, so a tiny position stays liquidatable (a reverting
  peek would block Moolah.liquidate and accrue bad debt); zero-leg-price
  still fails closed.

Counter-tests added for each.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
previewRemoveLiquidity (and its previewRedeemUnderlying wrapper) computed
spot principal + idle only, understating the withdrawal by uncollected
fees. Pro-rate positionAmountsAt(spot) instead — it simulates pending
fees + idle, matching removeLiquidity's actual spot-priced delivery.
Kept at spot (not fair) so the preview tracks the real burn for minAmount
sizing.

Counter-test accrues real swap fees and asserts the preview includes them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adding CLAMM liquidity is the one operation that must not be
permissionless: a manipulated pool spot lets a caller force a bad-price
re-add and sandwich it. Remove collectAndCompound from every
permissionless user flow (deposit, withdraw, withdrawShares,
supplyShares, redeemShares) and make compound() BOT-gated with a
caller-supplied slippage floor (amount0Min/amount1Min forwarded to
increaseLiquidity, previously hardcoded 0/0). Fee re-deployment now
happens only via compound() or rebalance, both BOT-gated.

No valuation regression: positionAmountsAt already simulates pending
fees, so the health-check / oracle valuation stays fee-complete without
an inline compound; removeLiquidity still collects the exiter's pro-rata
fees. Counter-tests: compound is onlyBot; a deposit no longer deploys
idle as liquidity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…comments with BOT-gating

Remove finding-ID / firm / process labels from shipped comments (no
logic change): C-1, H02/Issue_04, M01, finding C/C4/D, Codex adv, AUDIT
NOTE, "audit PR". Also correct two oracle @dev docstrings that still
claimed peek reverts on zero total value (it now floors a dust position),
and update the remaining compound comments that described the old
permissionless model (compounding is now BOT-gated; user flows no longer
compound).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ceil-round amount0Used/amount1Used in the subsequent-deposit branch so the
depositor pays >= their pro-rata share while shares still round down — every
sub-wei rounding now favors existing holders and can never dilute the pool.
Both legs stay <= the desired input (frac <= dᵢ·WAD/tᵢ), so no over-consumption.

Also strip internal finding-id / auditor-name references from the V3 provider
test comments (no behavior change; one test renamed accordingly).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rebase onto master auto-merged two copies of deposit() into IStakeManager
(and its mock) at different line positions — no textual conflict, but a
duplicate function definition that fails to compile. Remove the redundant
declaration; the interface keeps a single deposit()/instantWithdraw().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror Liquidator.sol's fund-pool integration onto V3Liquidator:
- fundSource (LiquidationVault) + reflowBlacklist storage, appended (UUPS-safe).
- initialize takes a fundSource arg (0 = legacy); set directly (contract check only —
  vault registration necessarily happens after the proxy exists) + setFundSource for later.
- setFundSource validates the vault has registered this liquidator; setReflowBlacklist.
- withdrawERC20/ETH gate relaxed to MANAGER or fundSource so the vault's collect* pulls.
- onMoolahLiquidate pulls the exact repayment shortfall from the vault (local balance first).
- liquidate/flashLiquidate/redeemV3Shares reflow the residue (loanToken + redeemed legs +
  native) to the vault; the transfer-restricted V3 share collateral is never reflowed.
- liquidate now routes a non-redeeming callback so the pool can fund it, and emits V3Liquidation.

fundSource == 0 preserves the exact legacy pre-funded behavior. Counter-tests cover
initialize+setFundSource validation, withdraw gate, vault-funded liquidate, and residue reflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The branch's IStakeManager (and its mock) add deposit() that new master also
declares — on the old base there was no clash, but rebased onto current master
the two collide into a duplicate function definition that fails to compile.
Remove the redundant declaration; a single deposit()/instantWithdraw() remains.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hashdit-bot

hashdit-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

Pull Request Review

This Solidity DeFi PR introduces a UUPS-based V3 collateral architecture comprising ERC-4626 provider vaults, concentrated-liquidity adapters, share-price oracles, and a dedicated liquidation contract for BSC and Ethereum LST/native pairs. It also adds rate-anchored valuation and rebalancing, native-token handling, loss and slippage controls, new dependencies, and extensive fork and regression tests.

Sensitive Content

No sensitive content detected.

Security Issues

🟠 [HIGH] Pre-existing native reserves can falsely satisfy flash-liquidation profitability

File: src/liquidator/V3Liquidator.sol
When the loan token is the wrapped-native asset, onMoolahLiquidate wraps the contract's entire native balance rather than only the native amount received during the current liquidation. Because the loan-token balance snapshot is taken before this conversion, pre-existing ETH/BNB reserves are counted as proceeds from the liquidation and can make an otherwise unprofitable operation pass out >= repaidAssets, allowing those reserves to be consumed for repayment.
Recommendation: Snapshot the native balance before redemption and wrap only the positive native balance delta attributable to the current liquidation. Add a regression test that pre-funds the liquidator with native currency, performs an unprofitable wrapped-native-loan liquidation, and verifies that it reverts without consuming the reserve.


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

razww and others added 13 commits July 29, 2026 18:52
…wap leg

In onMoolahLiquidate the native (BNB/ETH) leg was sold with
call{ value: actualRedeemedAmount }, but the bot builds the 1inch swapData
off-chain against a pre-estimated input. Native swaps require msg.value to
equal the amount encoded in the calldata, so the variable actual amount
mismatches and the aggregator reverts — failing the whole flash liquidation.

Send the pre-agreed minTokenNAmt (the value the swapData was built for) as
msg.value instead; redeemShares guarantees actual >= min so the balance always
covers it, and the leftover stays to be wrapped/reflowed. Mirrors the
smart-collateral path in Liquidator.sol. The ERC-20 leg is unaffected (approve
is a ceiling). Counter-test uses a strict aggregator mock (msg.value == amountIn);
V3LiquidatorEth test updated to set minToken1Amt to the native swap input.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
decreaseLiquidity settles the whole position's accrued fees into tokensOwed, so
collecting them together with the pro-rata burned principal paid a partial
withdrawer 100% of the fees — diluting the remaining holders. Collect the fees
into idle first (collect only claims owed tokens: no swap, no spot move, safe on
the user path), then burn the pro-rata principal and split idle+fees pro-rata.

Full redeems are unchanged (pro-rata = 100%). rebalance / _collectAndCompound
already keep collected fees in the vault for all holders, so they are unaffected.

Counter-test: with real accrued swap fees, a partial withdraw no longer drops the
remaining holders' per-share value.

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

A subsequent deposit's consumed amounts stay pinned to the fair composition, but
shares are now min(sharesFair, sharesSpot): the spot quote re-prices the same
consumed amounts against the pool-spot composition. Withdraw settles at spot, so
crediting only on fair let fair-valued shares be redeemed against a richer spot
composition (the deposit-withdraw cycle leak) — the min caps the credit at what a
spot exit can back. Manipulation-resistant (spot can only lower the credit, never
above fair); minShares is the depositor's MEV floor.

Add previewDepositShares mirroring the exact credit (shared _quoteDeposit helper so
preview can't drift from the mint) so frontends size minShares correctly. NatSpec
+ readable names on the new/changed functions and the IV3Provider surface.

Counter-tests: skewed-spot credits fewer shares, cycle no longer profitable,
minShares backstops a spot squeeze, and previewDepositShares == actual mint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A2 min(fair,spot) deposit crediting caps a large imbalanced deposit at its
spot-exit value, so surplus accrues to holders and the settled peek sits
above the pre-deposit price. Replace the stale "peek == normal price" check
with the true invariants: peekDuring == peekAfter (no transient inflation)
and peekDuring >= peekNormal (deposits only raise peek). The reentrancy attack
stays fully neutralized (attacker solvent, no bad debt).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WstETHV3Provider and WbETHV3Provider inherit V3Provider.deposit unchanged, so
the min(fair,spot) credit closes the deposit-withdraw cycle on the ETH pairs
too. Add cycle tests to both: a skewed spot credits fewer shares, preview ==
mint at a skewed spot, and the deposit->withdraw cycle extracts no value.

wstETH uses the deep live Uniswap V3 pool. The only wbETH/WETH pool is empty,
so the first deposit bootstraps it with our own liquidity under pure-rate mode
and a wide center band; the guard relaxation is scoped to the cycle tests so
the existing wiring assertions keep their defaults.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(provider): credit min(fair,spot) shares on deposit to close the deposit-withdraw cycle
rebalance takes an expectedCenterRate the BOT reads via the new adapter
centerRate() view and passes back; if the live LST↔native rate deviates from
it by more than maxCenterRateDeviationBps the call reverts. This bounds the
range anchor against a rate anomaly between build and execution — invisible to
the fair-NAV loss caps, which measure in the same rate frame.

Both sides opt in (expectedCenterRate != 0 per-call, maxCenterRateDeviationBps
!= 0 globally); 0 preserves prior behavior. Adds the MANAGER setter, the
centerRate() getter, and doc-faithful counter-tests (real slippage/target
floors, not zeros). Storage is append-only (upgrade-safe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v0.1.1 false-positived V3DexAdapter's __gap consumption (it read the __gap
array shrink 45->44 as a type change at the gap slot). v0.1.2 is __gap-aware:
the standard pattern — shrink __gap and place the new variable in the freed
slot — validates as UPGRADE SAFE, so the committed maxCenterRateDeviationBps
layout passes without contorting the storage.

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

feat(provider): assert expectedCenterRate on rebalance
sellBNB already measures actualIn from the balance delta and validates it, but
emitted the requested amountIn, so a venue that refunds part of the forwarded
value was logged as if the full amount was sold. That gave SellToken different
semantics per path: the ERC20 _sellToken emits the consumed amount, the native
path emitted the requested one. No fund-flow impact — ExceedAmount and NoProfit
already use the measured values — but off-chain accounting read the wrong input.

Counter-test drives a venue that consumes 0.6 of 1.0 BNB and refunds the rest;
it fails against the previous code (logs 1.0 instead of 0.6).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng, range params

Liquidator:
- onMoolahLiquidate counts native in the before-snapshot when the loan token is
  the wrapped-native, so stray native from earlier redemptions or receive()
  donations no longer reads as fresh profit and lets a shortfall clear NoProfit.
- redeemV3Shares requires receiver == self when a fundSource is set, keeping
  vault-funded proceeds inside the reflow path.
- setReflowBlacklist rejects a no-op status change, matching the other setters.

Provider:
- previewDepositAmounts rounds the leg amounts UP, matching _quoteDeposit, so the
  preview reports exactly what deposit() consumes.
- Range half-width INITIAL_RANGE_BPS 100 -> 50 (+/-0.5%), which also tightens the
  maxSpotDeviationBps and maxTwapDeviationBps defaults; centerRateThresholdBps
  drops to 1bp so the BOT, not the contract, picks the rebalance cadence.
- Correct two stale comments: the zero-liquidity guard covers compound only (the
  rebalance re-mint has none), and the spot-vs-fair gate does not apply to the
  rebalance re-mint. Drop the previewDepositForToken0 suggestion to deposit a
  single leg when fair leaves the range -- every shape reverts until a recenter.

Tests:
- Counter-tests for each liquidator fix, incl. a WBNB-loan market so the
  wrapped-native branch is exercised.
- previewDepositAmounts exact-match test; regression test pinning that deposits
  are closed while fair sits past tickUpper and reopen after a BOT recenter.
- _deposit helpers derive a non-zero minShares from previewDepositShares:
  min0/min1 floor the consumed amounts, not the entry price.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bailsec V3 Collateral final report (26 Jul, 75pp), HashDit V3 LP Collateral
(29 Jun - 14 Jul, 102pp) plus its follow-up update (24 - 28 Jul, 16pp), and
CertiK's preliminary comments on V3Provider (assessed 8 Jul, 93pp), filed under
the existing docs/audits naming convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hashdit-bot

hashdit-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

Pull Request Review

This Solidity DeFi PR introduces an upgradeable V3 concentrated-liquidity collateral system split across vault, DEX adapter, oracle, and liquidator contracts, with implementations for slisBNB/WBNB, wstETH/WETH, and wbETH/WETH. It also adds manipulation-resistant valuation, guarded rebalancing and liquidation flows, native-token handling, extensive fork/regression tests, audit artifacts, and CI/dependency updates.

Sensitive Content

No sensitive content detected.

Security Issues

No serious security issues detected.


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