Penpie Post-Mortem: Analysis of the $27M Reentrancy Exploit
4 sept 2024
5 Minutes
The Penpie platform — a farming protocol built atop Pendle Finance — suffered a devastating reentrancy attack that led to the loss of $27 million in client funds.
The attack occurred yesterday, September 3, after a vulnerability in Penpie's smart contract allowed the hacker to manipulate the system, exploiting a critical flaw in how markets were registered and validated within the protocol.
* Here is a visual representation of the attack.
Penpie immediately suspended all deposits and withdrawals and contacted security experts to prevent further damage. The protocol's swift response, in coordination with Pendle, helped to protect an additional $105 million that could have been at risk.
Disclaimer: The smart contract exploited in this attack was outside the scope of Zokyo's original audit. Changes to the code were made after we audited the function register pool compromised. However, we are committed to providing thorough insights on the matter to prevent future incidents.
Attack details
Attack Setup:
The main contract for the attack is PendleStaking but other important contracts that lead to the drainage of $27 million from the Penpie pool are
PendleMarketRegisterHelper
andPendleMarketFactoryV3
.The attacker could hack into Penpie by passing a fake pool address in the
batchHarvestMarketRewards(...)
method. Although this method checks if a market is valid or not validity depends on other contracts as well.
A market can be registered using the method
registerMarket(...)
in the same contract but it can be done only by the contract “PendleMarketRegisterHelper”.
When we check the
PendleMarketRegisterHelper
contract, it has another methodregisterPenpiePool
, which validates the pool address (but how?) and registers the market in the PendleStaking contract by callingregisterPool(...)
method.
As we can see in the above code, the method
registerPenpiePool
is permissionless but uses a modifieronlyVerifiedMarket
. When we check this modifier, we find that it is checking if the market address is valid or not by calling PendleMarketFactory contract. Let’s check the PendleMarketFactory then.The contract PendleMarketFactory has the following method to check the valid market contract.
But how are values pushed into the
allMarket
set and who can do it? The answer is in the below code.
As we can see from the above code, anyone can create a new market for a token and get its market validated as the method
createNewMarket(...)
is permissionless.This means any user can register a market (malicious) in the PendleStaking contract and harvest rewards.
So the attacker prepared a Standard Yield token, created a new market using it, configured two high-value PENDLE-LPT market tokens as reward tokens, and finally resisted it on the PendleStaking contract.
Attack Flow:
The attacker calls the
PendleStaking.batchHarvestMarketRewards(...)
method to harvest rewards which were calculated based on the difference in balanceOf() before and after theredeemRewards(...)
method was called.Method
redeemReward(...)
calls theclaimRewards()
for the specific market (malicious) which allowed the attacker to re-enter thePendleStaking.depositMarket(...)
method.Here attacker deposited the two high-value LP tokens to mint shares and also these LP tokens were considered reward tokens.
Then attacker can withdraw the deposited LP tokens along with the minted shares and claim the reward to make his profit.
Zokyo update
The _market parameter received in the batchHarvestMarketRewards(...)
method was not expected to be malicious as in the earlier version of the code audited by Zokyo, only the owner (multi-sig) can register a pool.
Earlier, the registerPool(...)
allowed only the owner to register a pool, unlike the current code which allows a contract to do the same.
This complete attack was possible because the attacker was able to register a pool in the PendleStaking
contract, due to the faulty code in the contract PendleMarketRegisterHelper
which considers any market valid if it’s created by a permissionless method in PendleMarketfactoryV3
contract.
After registering the pool, the attacker used the malicious market to re-enter the contract and drain millions of dollars.
Conclusion
The Penpie exploit highlights a significant vulnerability in DeFi protocols, particularly around permissionless functions and insufficient validation mechanisms. For other DeFi platforms, this incident serves as a crucial lesson in securing smart contracts, maintaining rigorous controls on market creation, and ensuring rapid incident response strategies.