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