# zlrewardscontroller contract is incompatible with zerolend's own reward bearing tokens

ZLRewardsController implements Radiant's handleActionAfter hook, but ZeroLend's Aave-forked tokens call handleAction, so reward accounting never updates.

- Payout: Contest reward
- Severity: high
- Program: Zerolend
- Credited: osmanozdemir1
- Disclosed: 2024-09-16
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_zerolend_jan2024.pdf#3.1.2
- Library page: https://bugbountylibrary.com/r/cantina%3Azerolend_jan2024%3A3.1.2
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:evm tech:solidity technique:incomplete-fix technique:source-review vuln:business-logic vuln:misconfiguration vuln:reward-distribution

**Target:** ZLRewardsController incentive contract and reward-bearing tokens
**Root cause:** ZLRewardsController was forked from Radiant Capital's ChefIncentivesController which uses handleActionAfter, but ZeroLend's token implementation (Aave fork) still calls handleAction, which the controller does not implement.
**Steps:**
1. Compare ZLRewardsController.handleActionAfter (L510) against Radiant ChefIncentivesController.handleActionAfter (L611-632).
2. Inspect ZeroLend AToken._transfer: it calls incentivesControllerLocal.handleAction(sender, currentTotalSupply, oldSenderBalance).
3. Observe ZLRewardsController exposes no handleAction function, only handleActionAfter.
4. Conclude balance-changing actions on ZeroLend tokens never invoke the reward hook, so user info/reward debt is never updated.
**How found:** Code-reading: noticed ZLRewardsController was a direct fork of Radiant's ChefIncentivesController, then checked whether ZeroLend's own token implementation (also an Aave fork) had been modified to call handleActionAfter like Radiant's — it had not, revealing the hook name mismatch.
**Exploitation:** No direct exploit path; the flaw causes reward accounting to silently fail — users' balances are never registered, so rewards are not distributed correctly and the incentive system is non-functional.
**Insight:** When auditing a forked incentive/reward controller, verify the hook name and signature against the actual token implementation in the target protocol, not the upstream fork it was copied from; forks often diverge on integration points.
