Last reviewed:

Penpie Reentrancy Exploit, September 2024

A reward function with no reentrancy guard sat in production for over a year without being a vulnerability. It became one the moment a different part of the system stopped checking who was allowed in — and the audit of that change did not look at it, because that code had not changed.

Date , 18:23 UTC
Protocol Penpie, a yield-boosting layer built on top of Pendle Finance
Loss 11,113.6 ETH, which Penpie valued at $27,348,259, across Ethereum and Arbitrum
Root cause Missing reentrancy protection, reachable only because pool registration had been made permissionless
Audited? Yes, three times, by three firms. None of the reports covered this combination.
Assets drained Market tokens for wstETH, sUSDe, egETH and rswETH, flash-loaned from Balancer

1. What happened

Penpie let depositors stake Pendle market tokens to earn boosted rewards. Its own post-mortem names two factors that had to combine: PendleStakingBaseUpg::batchHarvestMarketRewards() lacked reentrancy protection, and Penpie treated every Pendle market as a valid pool for registration while the creation of Pendle markets and their PT and YT tokens is itself permissionless.

So the attacker built their own market. They deployed a malicious Pendle market whose SY contract they controlled, registered it as a pool on Penpie, and minted a large quantity of fake YT and SY tokens. They then flash-loaned wstETH, sUSDe, egETH and rswETH from Balancer and parked them in that same SY contract.

Harvesting was then triggered on the malicious market. During the call, the attacker's SY contract declared the flash-loaned market tokens to be reward tokens, and re-entered the deposit path to pay them in while the reward accounting was still open. Penpie credited those rewards to the fake market's only depositor, which was the attacker, who claimed the lot, withdrew, and converted the market tokens back to their underlying assets.

Pendle paused its own contracts at 18:45 UTC, 22 minutes after the first transaction, and the last funds left via Arbitrum at 19:14. Penpie halted on all chains at 19:38. Penpie reports on-chain messages to the attacker seeking a whitehat settlement with no reply; The Block later reported an offer of a bounty, confidentiality and no legal action in exchange for cooperation.

2. Why three audits did not catch it

This is the part worth reading twice, and Penpie documented it against its own interest.

At launch in June 2023, registering a Pendle market on Penpie was restricted to the team's multisig. Two firms reviewed the contracts. Neither report mentioned reentrancy protection, and Penpie's own explanation is that there was no reason to: with registration permissioned, no attacker could introduce a malicious SY contract for the harvest function to call back into. The missing guard was not a defect, because the precondition that made it exploitable did not exist.

In May 2024, Penpie made pool registration permissionless. That removed the precondition. A third firm, AstraSec, audited the new registration feature — and here is the sentence that matters, from Penpie's post-mortem: because the PendleStakingBaseUpg contract had not undergone significant changes since the initial audit, it was not included in the scope of that audit.

The reasoning is standard practice. Review what changed. But what changed was not the vulnerable code; it was the assumption the vulnerable code had been safe under. Reviewing the diff could not surface that, because the diff was in a different file. Four months later someone registered a market of their own.

The rsETH case file shows an audit's perimeter failing to extend outward, to configuration and the infrastructure under it. This one shows it failing to extend backwards: unchanged code is not unchanged in its exposure if the system around it has moved.

3. Who actually lost money

Not, for the most part, people who had chosen Penpie. The assets drained were market tokens wrapping other protocols' receipts, and Penpie's post-mortem names the holders it had cost: agETH holders from Kelp DAO, rswETH holders from Swell, stETH holders from Liquid Staking Token issuer Lido, sUSDe holders from Ethena, and gUSDC holders from Gains.

Five protocols' depositors took a loss inside a sixth protocol, through a vulnerability in a seventh protocol's integration surface. Nobody in that chain had to do anything unusual. They deposited a receipt into a yield optimiser, which is what receipts are for.

4. Where the sources disagree

  • How much was saved by pausing. Pendle said it safeguarded around $105M. Penpie's own post-mortem puts the figure at approximately $70M, and attaches an exclusion — it does not count the vePendle position — which may be the whole of the difference. Both numbers come from parties to the incident, and neither has been reconciled publicly.
  • The loss figure. Penpie states 11,113.6 ETH and $27,348,259. Lookonchain, via The Block, gives roughly $27.3M and 11,109 ETH. The smaller token figure matches the 11,109.62 ETH the post-mortem's own timeline records the attacker moving to a fresh wallet at 20:16 UTC, which is a subset of the total rather than a competing count of it.
  • How to characterise the cause. PeckShield, quoted by The Block, described the root cause as the introduction of an "evil market" inflating staking balances. Penpie names the reentrancy gap plus permissionless registration. These are the same event described from the outside and the inside; the second is more specific.
  • One documentary inconsistency. In the post-mortem's list of audit reports, the entry labelled as Zokyo's report links to a file named WatchPug_V1.pdf, and the entry labelled as WatchPug's links to Zokyo_V1.pdf. Either the labels or the filenames are wrong. We could not establish which from the documents themselves, so the two reports are linked below by filename and neither is attributed to a firm here. This does not affect the account above, which turns on what the reports did not contain rather than on who wrote them.

5. What it shows about restaking risk

Our risk questions ask how many separate smart contract systems sit between a deposit and a withdrawal, on the reasoning that each one is an independent failure surface. This incident is a warning about how that question is answered in practice. A depositor counting layers in September 2024 would have counted Pendle, Penpie and their own receipt issuer, found audit reports for all of them, and concluded the stack was reviewed. It was. The reports were real, the firms were real, and the finding that mattered was in none of them because no single review ever held both halves of the problem at once.

The durable point is about time, not count. A contract audit is a statement about a specific set of files under a specific set of assumptions on a specific date. Restaking stacks are built by adding permissionless surfaces to systems that were designed with permissioned ones, and each such addition silently re-opens every review that depended on the old assumption. Nothing in a list of completed audits records which assumptions they rested on.

Sources

Every figure above comes from one of the following. Dates are publication dates, and these links open in a new tab.

  1. Penpie Post-Mortem Report — Magpie, on Penpie's blog, 4 September 2024. The affected protocol's own account, and the source of the timeline, the attack flow and the audit history. A party to the event, and unusually candid about the scoping decision that cost it.
  2. Pendle says it saved $105 million that could have been further drained amid Penpie hack — James Hunt, The Block, 4 September 2024. Source of Pendle's own $105M figure, the Lookonchain token count and PeckShield's characterisation.
  3. Penpie Hack Analysis — BlockApex, 2024. Independent reconstruction of the attack steps, consistent with the post-mortem. A security vendor, and it states that its impact data came from Penpie.
  4. Penpie V1 audit report, Zokyo_V1.pdf and Penpie V1 audit report, WatchPug_V1.pdf — the two launch-era reviews, published by Magpie. Identified by filename only, because the post-mortem's labels for them do not match their names; see section 4.
  5. AstraSec incremental audit report — AstraSec. The review of the permissionless registration feature whose scope excluded the contract that was exploited.

Pendle's post-mortem was published as a post on X rather than as an article, so it is cited here through The Block's report of it rather than directly.

This page is explanatory and not a recommendation. Naming the organisations above records a documented event and reproduces their own published statements; it is not an allegation of wrongdoing and not a safety assessment.