You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
No high or critical severity finding was classified in this static review. The flashloan finding is kept at medium because every affected entrypoint first requires an approved contract-caller.
Top 3 Findings
Medium: the flashloan liquidation flow is split across two public steps, does not call the flashloan-script parameter, and relies on approved callers to enforce atomic repayment.
Medium: collateral and e-mode risk-parameter setters do not locally cap LTV/liquidation thresholds to fixed-point maximums.
Low: add-isolated-asset and set-borroweable-isolated can place assets into isolated-mode configuration without local duplicate/existence checks.
State Model
Local Stores
Line
Store
Meaning
Mutated by
47
users-id
Map from local incrementing user ID to principal
supply
49
last-user-id
Next user ID counter
supply
623
configurator
Principal allowed to configure protocol/reserve settings
set-configurator
992
approved-contracts
Allowlist for helper/router contracts permitted to call user-facing pool entrypoints
set-approved-contract
External State Dependencies
Contract
State / behavior used
.pool-0-reserve-v2-0
Reserve state, user reserve data, global health calculations, collateral toggles, supply/borrow accounting, reserve transfers, flashloan accounting
tx-sender is used to bind user actions to owner, payer, or who, while contract-caller is used as the approved helper/router gate. This is a deliberate pattern but makes the allowlist critical.
unwrap-panic appears in user-facing or configuration-adjacent paths at lines 91, 929, and 944. Prefer explicit try!/unwrap! errors for predictable failures.
No as-contract principal escalation was observed in this contract; most privileged writes are delegated by direct contract calls.
Oracle trait references are validated against reserve state before withdraw/borrow/liquidation flows. The caller-provided full asset list is also validated by order and length.
Configuration functions often delegate validation to reserve-data contracts. Where local constants/errors indicate intended bounds, local assertions would make failures easier to audit.
The flashloan liquidation flow is split into two public functions. Step 1 transfers principal to receiver, step 2 separately pulls principal plus fee back, and the flashloan-script parameter is never called in either function. Because both steps are gated by is-approved-contract contract-caller, this is not directly callable by arbitrary users, but any approved wrapper must enforce atomic step1/liquidation/step2 sequencing perfectly.
Replace the split public pattern with one public function that calls the receiver/script callback and verifies repayment before returning, or make step 1 private/internal to a trusted orchestrator. At minimum, remove the unused flashloan-script parameter or use it in the same transaction.
Risk-parameter setters accept base-ltv-as-collateral, liquidation-threshold, liquidation-bonus, e-mode ltv, and e-mode liquidation-threshold without local bounds. If downstream reserve-data contracts do not enforce caps, configurator mistakes can set unsafe ratios or impossible health-factor behavior.
Assert fixed-point ratios are within documented ranges, for example ltv <= liquidation-threshold <= one-8, and bound liquidation bonus to a protocol maximum before writing reserve/e-mode config.
ZEST-03
Low
add-isolated-asset, set-borroweable-isolated
901-906, 924-931
Isolation configuration can add assets without local existence and duplicate checks. set-borroweable-isolated appends to the allowlist and uses unwrap-panic on max length; it does not check whether the asset is already present or whether it is an initialized reserve.
Require asset reserve existence, reject duplicates before append, and return an explicit error when the list is full.
ZEST-04
Low
supply, set-borroweable-isolated, filter-asset
91, 929, 944
unwrap-panic is used where explicit errors would be safer. In supply, a validation helper is unwrapped with panic; in isolation-list updates, list-bound failures panic instead of returning a protocol error.
Replace with try! or unwrap! and a defined error such as ERR_PANIC or a more specific new error.
ZEST-05
Low
borrow
221
The inactive-reserve check uses ERR_FROZEN instead of ERR_INACTIVE. This does not change acceptance logic, but it makes monitoring and integrator handling misleading.
Return ERR_INACTIVE when is-active is false.
ZEST-06
Informational
supply
84-85
Every supply call inserts the owner into users-id and increments last-user-id, even for repeat suppliers. The map therefore records duplicate owner principals over time and does not represent unique users.
If the map is intended for unique-user indexing, add a reverse lookup or only insert first-time suppliers. Otherwise document that it is an append-only supply-event index.
Additional Notes
validate-assets is strict: it requires caller-provided assets to match the reserve asset list by length and order. This is good for preventing mismatched oracle/a-token inputs, but frontends must keep the asset list fresh.
repay intentionally allows a payer to repay on behalf of a different borrower while requiring payer == tx-sender.
Configuration authority is intentionally broad. The findings above focus on missing local validation and operator-footgun risk rather than assuming the configurator is malicious.