# EquilibriaEPendle: reward debt not updated on share transfer

VaultEPendle failed to update reward debt on share transfers, letting an attacker cycle shares through fresh receivers to repeatedly claim historical ETH rewards.

- Payout: Real-world hack
- Severity: high
- Program: EquilibriaEPendle
- Credited: DeFiHackLabs
- Disclosed: 2025-08-23
- Write-up quality: 8/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-08/EquilibriaEPendle_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250823-equilibriaependle
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:chained vuln:business-logic vuln:flash-loan vuln:reward-distribution

**Target:** VaultEPendle staking vault (ERC20 shares, getReward)
**Root cause:** VaultEPendle did not update reward debt when ERC20 shares were transferred, and getReward(address) recomputed rewards for arbitrary fresh receiver accounts with zero debt.
**Steps:**
1. Flash-loan all ePendle from Balancer Vault.
2. Deposit ePendle into VaultEPendle to mint stk-ePendle shares.
3. Transfer shares to a fresh RewardReceiver contract (zero reward debt).
4. Call `getReward(receiver)` to claim historical native ETH rewards.
5. Transfer shares back to attacker contract and repeat with new receiver (20 iterations).
6. Withdraw ePendle and repay Balancer flash loan.
**How found:** Likely spotted that VaultEPendle's `getReward(address)` accepted an arbitrary account and that share transfers did not update reward debt, enabling repeated claims from fresh addresses.
**Exploitation:** Attacker flash-loaned ePendle, deposited into VaultEPendle, then repeatedly moved the same stk-ePendle shares into fresh receiver contracts. Each fresh receiver had zero reward debt, so `getReward(receiver)` paid out historical ETH rewards again. Receiver forwarded ETH to attacker before shares were pulled back. Repeated 20 times, draining >13 ETH.
**Insight:** In staking/reward vaults, check whether reward debt is updated on share transfers and whether `getReward` can be called for arbitrary addresses with zero debt; cycling shares through fresh contracts can re-claim historical rewards.
