# Self-lender inflates repaid totals

Repay or migrate paths that increment counters without the matching prior increment or guard

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2025-06-18. Updated 2026-10-29._

## How it works
A counter meant to track real economic activity is incremented on a path that does not require that activity to have happened. In the core case, a pool tracks `totalPrincipalTokensLended` (bumped only when funds are accepted) and `totalPrincipalTokensRepaid` (bumped by a repayment-listener callback). Listener registration is gated only by `sender == bid.lender`, with no check that the borrower is not also the lender. A borrower who is also the lender registers a listener on their own bid; on repayment the callback raises the repaid total without any matching lend increment, so the two counters diverge and downstream outstanding-principal math underflows.

## Where it shows up
- Paired counters (lended/repaid, minted/burned) written from different entry points.
- Listener or callback registration gated only by `sender == bid.lender`, with no borrower != lender check.
- Migration functions writing new mapping state that defaults to zero for legacy entries, with no already-set guard.
- Any increment with no symmetric decrement or precondition check.

## How to review
For every counter, identify the exact event that must precede its increment and confirm the code enforces it. The invariant: a repaid/credited total can only rise for positions that previously raised the corresponding lended/debited total, and self-dealing (payer == recipient) cannot satisfy both. Check that listener registration rejects the borrower-as-lender case, and that migration paths re-check the same guard as the normal path.

## Variants seen
- Borrower registers a repayment listener on their own bid, inflating repaid totals and underflowing pool accounting [E1](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-3.md).
- Adjacent, not an instance: public `buyFor` spends a victim's allowance to force pool buys, inflating dividends before withdrawal [E2](https://bugbountylibrary.com/r/dhl%3A20250618-bankrollstackplus.md).
- Adjacent, not an instance: `tryMigrate()` skips the already-following check, double-counting followerCount [E3](https://bugbountylibrary.com/r/c4%3A2023-07-lens%3AM-02.md).

## Impact and severity
High: pool bricking via underflow [E1](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-3.md). Worse when the inflated counter feeds share price or withdrawal math, and when no consent or role check stands between attacker and the increment.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-3.md
- E2: https://bugbountylibrary.com/r/dhl%3A20250618-bankrollstackplus.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-07-lens%3AM-02.md
