Findings

Individual findings from static detectors and the repository mapper, with their relationship to attack chains and validation status.

  • HighUnprotected oracle price-source setterF-001 · Access controlSpotPriceOracle.setPool()contracts/SpotPriceOracle.sol:L18–21Part of attack chainSupported

    SpotPriceOracle.setPool can be called by any account. The contract stores an owner but never checks it, so any caller can replace the pool used for pricing.

    Confidence 90%Related:F-002F-003Investigate CG-001
    • E-01Access controlVerifiedsetPool is external and writes `pool` with no msg.sender check or modifier. `owner` is stored in the constructor but never enforced.
    • E-02State dependencyVerifiedWrites state variable `pool`, which getPrice() reads to compute the collateral price.
    • E-11Static detectorVerifiedSlither detector `missing-zero-check`: newPool is not validated before being assigned to `pool`.
  • HighCollateral priced from single-pool spot reservesF-002 · Oracle / price manipulationSpotPriceOracle.getPrice()contracts/SpotPriceOracle.sol:L24–28Part of attack chainSupported

    getPrice() returns reserveDebt / reserveCollateral from the configured pool with no time-weighting or bounds, so the returned price is whatever the pool reports at call time.

    Confidence 82%Related:F-001F-003F-008Investigate CG-001
    • E-03External dependencyVerifiedPrice is derived from the instantaneous reserves of one pool. No TWAP, staleness check, or deviation bound is applied.
  • HighCross-function reentrancy from withdrawCollateral into borrowF-004 · Reentrancy · reentrancy-ethLendingVault.withdrawCollateral()contracts/LendingVault.sol:L43–52Part of attack chainDetected

    withdrawCollateral sends ETH to msg.sender before decrementing collateral. During that call, borrow() still sees the pre-withdraw collateral balance.

    Confidence 84%Investigate CG-002
    • E-07Static detectorVerifiedSlither detector `reentrancy-eth`: external call sends ETH before state variable `collateral` is written; `collateral` is read by borrow().
    • E-12Source codeVerifiedNative ETH is sent to msg.sender, handing execution to the caller before collateral is decremented.
    • E-13State dependencyVerified`collateral` is written only after the external call returns.
    • E-14State dependencyVerifiedborrow() reads collateral[msg.sender] through collateralValue(); the value is stale during withdrawCollateral’s external call.
  • MediumBorrow limit trusts an unbounded oracle priceF-003 · Logic / arithmeticLendingVault.borrow()contracts/LendingVault.sol:L37–41Part of attack chainSupported

    borrow() allows debt up to 75% of collateralValue(), which multiplies collateral by the raw oracle price. An inflated price increases the borrow limit without bound.

    Confidence 78%Related:F-001F-002Investigate CG-001
    • E-04Call dependencyVerifiedCross-contract call LendingVault.collateralValue → SpotPriceOracle.getPrice. Collateral value scales linearly with the returned price.
    • E-05Call dependencyVerifiedborrow → maxBorrow → collateralValue. The borrow limit has no upper bound independent of the oracle price.
    • E-06External dependencyVerifiedDebt token leaves the vault immediately after the collateral check passes.
  • MediumUnchecked return value of send() in claimF-005 · Unchecked external call · unchecked-sendRewardDistributor.claim()contracts/RewardDistributor.sol:L22–26IsolatedDetected

    claim() zeroes the accrued reward and then ignores the boolean returned by send(). If the send fails, the reward is lost for that account.

    Confidence 92%
    • E-08Static detectorVerifiedSlither detector `unchecked-send`: return value of send() is ignored.
    • E-17Source codeVerifiedaccrued[msg.sender] is zeroed before send(); a failed send silently forfeits the reward.
  • MediumTreasury authorization relies on tx.originF-006 · Access control · tx-originTreasury.sweep()contracts/Treasury.sol:L12–15IsolatedDetected

    sweep() checks tx.origin == owner. A malicious contract the owner interacts with can call sweep() and redirect the treasury balance.

    Confidence 88%
    • E-09Static detectorVerifiedSlither detector `tx-origin`: authorization uses tx.origin.
    • E-18Access controlVerifiedA contract the owner interacts with can call sweep() and pass the tx.origin check.
  • MediumOracle reserves may be flash-loan manipulableF-008 · Flash-loan surfaceSpotPriceOracle.getPrice()contracts/SpotPriceOracle.sol:L25UnverifiedUnverified

    Even with setPool restricted, a legitimate pool’s spot reserves could be moved with borrowed liquidity inside one transaction. The pool and any flash-loan source are outside this repository, so the path cannot be validated.

    Confidence 35%Related:F-002
    • E-16AI reasoningUnverifiedSpot reserves of a legitimate pool could be moved with borrowed liquidity. No flash-loan provider or pool implementation is present in the repository, so this cannot be validated.
  • InformationalFloating compiler pragmaF-007 · Other · solc-versionLendingVaultcontracts/LendingVault.sol:L2IsolatedDetected

    Contracts use pragma ^0.8.20. Pinning an audited compiler version makes builds reproducible.

    Confidence 95%
    • E-10Static detectorVerifiedSlither detector `solc-version`: floating pragma ^0.8.20 allows compiler versions with known issues.