The September 2024 Penpie Finance exploit that drained $27 million through a reentrancy attack on a Pendle-based yield farming protocol exposed a critical gap in DeFi security practices. The attacker exploited the harvestBatchMarketRewards function in Penpie’s PendleStakingBaseUpg contract, which lacked a reentrancy guard, using flash-loaned assets and malicious Standardized Yield tokens to manipulate reward calculations. This advanced tutorial walks through the technical mechanics of reentrancy vulnerabilities, demonstrates how to identify them during code review, and provides a systematic auditing framework that would have caught the Penpie vulnerability before deployment.
The Objective
This tutorial aims to equip experienced developers and security researchers with a practical methodology for identifying reentrancy vulnerabilities in Solidity smart contracts. By the end of this guide, you will understand the specific attack pattern used against Penpie, be able to identify similar vulnerability patterns in other DeFi protocols, and know how to implement and verify proper reentrancy protections. The techniques covered go beyond basic reentrancy detection to address the compound attack vectors — flash loan manipulation, fake token contracts, and permissionless market registration — that made the Penpie exploit possible.
Prerequisites
This guide assumes familiarity with Solidity development, the Ethereum Virtual Machine, and basic DeFi concepts including yield farming, liquidity pools, and token standards such as ERC-20 and ERC-4626. You should have experience reading smart contract code and understanding function execution flows. Familiarity with Foundry or Hardhat testing frameworks will help you follow the verification examples, though the core concepts are language-agnostic.
Key tools you should have installed: Foundry (for Solidity compilation and testing), Slither (for static analysis), and access to a block explorer such as Etherscan for transaction analysis. Understanding of the EVM’s call stack and storage layout is essential for grasping why reentrancy attacks work and how to prevent them.
Step-by-Step Walkthrough
Step 1: Understanding the Penpie Attack Vector. The Penpie exploit combined three vulnerability elements. First, the protocol allowed permissionless registration of Pendle Markets, meaning anyone could register a malicious contract. Second, the harvestBatchMarketRewards function lacked a reentrancy guard — a modifier that prevents the function from being called again before its first execution completes. Third, the function relied on balance differences to calculate rewards, a pattern that becomes exploitable when the balance can change during execution through reentrant calls.
The attacker deployed a malicious SY token contract that, when called by the harvest function, would re-enter the harvest function itself. During this reentrant call, the attacker deposited additional flash-loaned tokens (wstETH, sUSDe, egETH, and rswETH), artificially inflating the balance. When the original harvest function completed, it calculated rewards based on the inflated balance difference, crediting the attacker with far more tokens than they legitimately earned.
Step 2: Identifying the Checks-Effects-Interactions Violation. The root cause was a violation of the Checks-Effects-Interactions pattern. In secure contract design, a function should first check all preconditions (Checks), then update all internal state variables (Effects), and only then interact with external contracts (Interactions). The Penpie function performed Interactions — calling external token contracts to check balances — before completing its Effects — updating the reward state. This ordering allowed the external call to trigger a reentrant path that manipulated the state the function relied upon.
To identify this pattern in code review, trace every external call in a function and verify that no state variables are read after the call that could have been modified by the call’s execution path. Pay particular attention to functions that calculate values based on balanceOf differences, as these are prime reentrancy targets.
Step 3: Implementing Reentrancy Guards. The most straightforward protection is the OpenZeppelin ReentrancyGuard modifier. Apply nonReentrant to any function that makes external calls and depends on internal state. For Penpie’s case, the fix is a single modifier addition:
modifier nonReentrant() { require(!_entering, "ReentrancyGuard: reentrant call"); _entering = true; _; _entering = false; }
However, basic reentrancy guards are not always sufficient for complex protocols. Consider also implementing a global reentrancy lock that prevents any state-changing function from being called during reward calculation, and validate that any registered market contracts implement expected interfaces rather than accepting arbitrary contract addresses.
Step 4: Auditing Permissionless Registration Patterns. Penpie’s permissionless market registration allowed the attacker to register their malicious contract without validation. When auditing protocols that accept external contract registrations, verify that: (1) registered contracts implement required interfaces through interface checks, (2) there is a registration delay or governance approval process for new markets, (3) registered contracts cannot re-enter critical functions, and (4) emergency pause mechanisms exist to freeze operations if suspicious activity is detected.
Troubleshooting
False positives in static analysis: Tools like Slither may flag functions that appear to have reentrancy potential but are actually safe due to access controls or other protections. Always manually verify findings and trace the full execution path before reporting a vulnerability. Focus particularly on functions marked external or public that interact with user-supplied contract addresses.
Flash loan attack surface: The Penpie exploit used flash loans to amplify the attack. When auditing, consider whether an attacker could use flash loans to manipulate any balance or price oracle that a function depends on. If a function reads balanceOf from an ERC-20 token, assume that balance could change dramatically within a single transaction through flash loans.
Proxy contract risks: Penpie used upgradeable contracts (indicated by the Upg suffix). Upgradeable contracts add complexity to audits because the implementation can change after deployment. Verify that proxy admin controls are properly secured and that any upgrade mechanism includes a timelock that allows users to review changes before they take effect.
Mastering the Skill
Becoming proficient at identifying reentrancy vulnerabilities requires systematic practice. Study the major reentrancy exploits chronologically — from the 2016 DAO hack through the 2024 Penpie exploit — to understand how attack patterns have evolved. Each generation of attacks builds on the lessons of previous exploits, and attackers continuously develop new techniques that bypass established protections.
Contribute to audit competitions on platforms like Code4rena, Sherlock, and Cantina. These competitions expose you to real-world codebases and diverse vulnerability patterns. Build a personal checklist of reentrancy indicators: external calls before state updates, balance-dependent calculations, permissionless contract registration, and missing reentrancy guards on critical functions.
Finally, develop automated detection tools. Write custom Slither detectors for the specific patterns identified in this tutorial, create Foundry test suites that simulate reentrancy attacks against target contracts, and contribute your findings to the broader security community through blog posts and responsible disclosure. The DeFi ecosystem’s security improves only when researchers share their knowledge and tooling openly.
Disclaimer: This article is for educational purposes only. Smart contract auditing is a complex discipline, and this guide does not guarantee the identification of all vulnerabilities. Always engage professional auditors before deploying contracts that handle user funds.
finally someone explaining reentrancy beyond the classic counter++ example. the pendleStakingBaseUpg case with fake SY tokens is way more nuanced than textbook attacks
l33tcrypto the fake SY token pattern is becoming standard. penpie, eigenlayer, multiple exploits this year using malicious token callbacks in the same call stack
the fake SY token angle is what makes this exploit genuinely clever. most reentrancy guards check for msg.sender reentry but not for malicious token contracts in the same call
the systematic auditing framework mentioned here should be required reading for anyone deploying DeFi contracts. especially the part about checking cross-function reentrancy, not just single-function
cross-function reentrancy is the blind spot in most audits. auditors check individual functions but miss the interaction between harvestBatchMarketRewards and the token callbacks
reentrancy guards cost like 200 gas. not using one on a function handling $27M in TVL is negligence not a bug
$27m because one function missed a reentrancy guard. the cost of a single require() statement vs the damage is absurd. protocol devs need to treat every external call as hostile