Skip to content
KVΛZAR

// Case study

PLACEHOLDER: Pre-launch audit of a fictional lending protocol

Fake sample case study. Two weeks, twelve contracts, and a critical found by the agent that manual review had marked as safe.

  • A. Placeholder · Security researcher

8 min read

  • DeFi

// Key results

Client
Acme Lending (fictional)
Scope
12 contracts · 4.2k LoC
Findings
23
  • 1 critical
  • 3 high
  • 5 medium
  • 8 low
  • 6 info

Outcome — All criticals fixed before launch

PLACEHOLDER BODY — every word on this page is sample content. It exists so the layout, table of contents, code blocks, callouts, tables, embeds and footnotes can be seen before real research is published.

Background

The contract below is a deliberately broken vault used throughout our sample content. It is not client code. The withdraw path makes an external call before updating state, which is the textbook reentrancy shape.

This pattern has been documented since 2016[1], and it still ships.

The vulnerable code

contracts/Vault.sol
contract Vault {
  mapping(address => uint256) public balances;

  function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount);
    // state is updated after the external call
    (bool ok, ) = msg.sender.call{value: amount}("");
    balances[msg.sender] -= amount;
  }
}

Why it matters

Because the balance is decremented after the call returns, a receiver contract can call withdraw() again from its fallback while its balance is still unchanged.

The fix

Vulnerablecontracts/Vault.sol
function withdraw(uint256 amount) external {
  require(balances[msg.sender] >= amount);
  (bool ok, ) = msg.sender.call{value: amount}("");
  balances[msg.sender] -= amount;
}
Fixedcontracts/Vault.sol
function withdraw(uint256 amount) external nonReentrant {
  require(balances[msg.sender] >= amount);
  balances[msg.sender] -= amount;
  (bool ok, ) = msg.sender.call{value: amount}("");
  require(ok, "transfer failed");
}

Severity rationale

FactorAssessment
LikelihoodHigh — any depositor can trigger it
ImpactCritical — total loss of funds
ComplexityLow — a 20-line attacker contract
Sample severity matrix

Disclosure

Reported privately, acknowledged within a day, and fixed in the following release. The timeline is listed above the article on research pages.

// Footnotes

  1. [1]Sample footnote. In a real article this would cite the commit, the advisory or the prior work being referenced. ↩

// Share

XLinkedIn

// More case studies