# Allowance checked on wrong unit or account

Allowance compared on shares, part, or recipient while a larger elastic amount or different account moves

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; one confirmed bounty: $560,000; latest 2023-11-16. Updated 2026-10-25._

## How it works
An approval is a cap on what a spender may move from an owner. The bug is that the cap is computed on a different quantity than the one actually transferred. Two mismatches recur: the wrong account (allowance read from the recipient but written for the caller) and the wrong unit (allowance checked on a share/part value while the transfer moves the converted, larger asset amount). In both cases the check passes on a small or unrelated number while a bigger real amount leaves the owner's balance.

## Where it shows up
- Hand-rolled or forked ERC-20 `approve`/`transferFrom` instead of OpenZeppelin.
- `transferFrom` where the allowance read key and the allowance write key differ (recipient vs `msg.sender`).
- Access-control modifiers (`allowedBorrow`, allowance checks) applied to a raw parameter that is later derived or normalized inside the function body.
- Sentinel values (e.g. `share == 0`) that trigger conversion after the check has already run.
- `repay`/withdraw paths that validate allowance on `part`/`base` but transfer the `elastic` amount.

## How to review
The invariant: the allowance key and unit used in the check must be identical to the key and unit used in the state change and transfer. Concretely:
- Confirm the same `(owner, spender)` pair is read and decremented; the spender is `msg.sender`, never the recipient.
- Confirm the checked value is the final amount moved, after any share-to-asset conversion, not the raw input.
- Confirm modifiers guarding a parameter run after that parameter is normalized, or guard the derived value.
- For share/asset pairs, verify the check uses the same unit as the transfer and that exchange-rate drift cannot exceed the cap.

## Variants seen
- Allowance read from recipient, written to caller, granting caller the recipient's approval [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-redacted-cartel-custom-approval-logic-bugfix-review.md).
- Modifier checks raw `share` (0) before conversion; real shares pulled from victim's approval [E2](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-05.md).
- Allowance checked on `part` but `elastic` withdrawn, exceeding approval as interest accrues [E3](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-44.md).

## Impact and severity
Led to theft of user funds and, in E2, infinite collateral inflation and unlimited borrowing. Severity is high: the flaw defeats the approval boundary entirely. It worsens when exchange-rate divergence grows over time (accrued interest) or when a sentinel value makes the check trivially pass.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-redacted-cartel-custom-approval-logic-bugfix-review.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-05.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-44.md
