Reproduced Exploit

maxRedeem permits leverage above the configured buffer — AuditVault synthetic reduction

A bug report has been identified in the Vault leverage calculations. The bug is caused by incorrect maxRedeem calculations with closable and LEVERAGE_BUFFER. This was found by panprog. The bug means that it is possible for users to increase the Vault leverage to any value up to the minimum margin r…

Oct 2023Otherlogic4 min read

Chain

Other

Category

logic

Date

Oct 2023

Source

AuditVault

EVM Playground

Source-level debugger — step opcodes and Solidity in sync

evm-hack-analyzer

The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.

Loading fork state…

Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 28949-h-2-vault-leverage-can-be-increased-to-any-value-up-to-min-m. Standalone Foundry PoC and full write-up: 28949-h-2-vault-leverage-can-be-increased-to-any-value-up-to-min-m_exp in the evm-hack-registry mirror.


Vulnerability classes: vuln/logic/incorrect-state-transition · vuln/logic/price-calculation

Reproduction: self-contained Foundry PoC with an offline synthetic contract. Full trace: output.txt.

AuditVault finding: 28949 · H-2: Vault leverage can be increased to any value up to min margin requirement due to incorrect maxRedeemcalculations with closable andLEVERAGE_BUFFER``

Key info#

ImpactHIGH — maxRedeem permits leverage above the configured buffer
Protocol[[Perennial]]
FindingAuditVault #28949
Reporthttps://github.com/sherlock-audit/2023-10-perennial-judging
SourceAuditVault finding
Compiler^0.8.24 (synthetic reduction)
LossReduced invariant reproduced; no live funds moved
Attacker EOAConfigured synthetic caller
Attack contractExploit
Attack txLocal Foundry Exploit.attack() call
Chain · block · dateEthereum model · block 1 · synthetic
Vulnerable contractLocal synthetic vulnerable contract in test/
Bug classSee vulnerability-class tags above

TL;DR#

A bug report has been identified in the Vault leverage calculations. The bug is caused by incorrect maxRedeem calculations with closable and LEVERAGE_BUFFER. This was found by panprog. The bug means that it is possible for users to increase the Vault leverage to any value up to the minimum margin requirement. This is done by redeeming an amount higher than the closable allows. This is done indirectly by limiting the maker limit in the underlying market. The result of this bug is that a malicious user could put the Vault at a very high leverage, breaking the important protocol invariant of not exceeding the target market leverage. This could expose users to a much higher potential of funds loss due to the high leverage and a high risk of Vault liquidation. This would cause additional loss of funds from liquidation penalties and position re-opening fees. A proof of concept was provid

Background#

The upstream report is a Solidity finding. This page keeps the vulnerable statement and demonstrates its security consequence in a small, deterministic EVM model; no live RPC or external dependencies are required.

The vulnerable code#

SOLIDITY
// The exact vulnerable pattern is retained in test/28949-h-2-vault-leverage-can-be-increased-to-any-value-up-to-min-m.sol.
// @> see the marked statement in the synthetic reduction

Root cause#

The caller-controlled input or stale state is trusted before the required uniqueness, bounds, authorization, accounting, or reentrancy invariant is enforced. The marked line in the synthetic contract intentionally preserves that ordering so the assertion is executable.

Preconditions#

  • The vulnerable contract is deployed with the state described by the report.
  • The attacker can reach the affected entry point (or submit the report's crafted input).

Attack walkthrough#

  1. Exploit.run() initializes the minimal state from the report.
  2. The marked vulnerable operation executes without its required check.
  3. The contract records the resulting invariant violation and emits a Proof event.
  4. The test asserts the harm; the passing trace is recorded at output.txt:4.

Diagrams#

flowchart TD A[Attacker supplies crafted input] --> B[Vulnerable operation] B --> C{Missing invariant check} C --> D[Security impact demonstrated]
sequenceDiagram participant A as Attacker participant V as Vulnerable contract participant S as State A->>V: invoke affected entry point V->>S: apply unchecked update S-->>A: harm is observable

Remediation#

Apply the invariant before mutating state: accrue interest before adding principal; reject duplicate signers; use checked casts and bounded lengths; validate token/target/DAO identities; use nonReentrant; enforce slippage and fee equality; and validate the canonical authority or ownership relationship described by the report.

How to reproduce#

BASH
cd evm-hack-registry/28949-h-2-vault-leverage-can-be-increased-to-any-value-up-to-min-m_exp
forge test -vvvvv

The test is offline and uses only the shared forge-std library. The corresponding Playground bundle is generated from scripts/poc-configs/28949-h-2-vault-leverage-can-be-increased-to-any-value-up-to-min-m.mjs.

Sources#

Reference: https://github.com/sherlock-audit/2023-10-perennial-judging


Sources & further analysis#

Reproductions & code

Alerts & third-party analyses

  • Web3Sec X hacked database: search.
  • Rekt leaderboard: search.
  • Solodit incident search: search.

These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.