# Sentinel value collides with valid input

Sentinel addresses, max/zero amounts, and default field values that overlap real inputs and break checks

_Area: Smart contract access control and control flow. Seen in 11 disclosed reports; latest 2025-07-21. Updated 2026-10-23._

## How it works
Code uses a special value (a sentinel) to mean "native asset", "repay everything", "no lender", or "unset". The bug appears when that sentinel is also a legal input, or when the sentinel is compared against a field that actually stores a different value. A guard that was meant to skip or short-circuit one path then fires on the wrong path, or fails to fire at all, so a check is bypassed or a valid operation reverts.

## Where it shows up
- Branches on a sentinel address (`_ETH_ADDRESS_`, `address(0)`, `0xEeee...`) that skip a `transferFrom` or approval check [E1](https://bugbountylibrary.com/r/sherlock%3A2025-05-dodo-cross-chain-dex%3AH-2.md)[E8](https://bugbountylibrary.com/r/sherlock%3A2023-02-notional%3AM-4.md)
- Hardcoded `type(uint256).max` meaning "full amount" passed into external calls [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-17.md)
- Sentinel addresses written to storage (e.g. `USING_LENDER_MANAGER`) then read by direct `==` comparisons [E6](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1.md)
- Struct fields initialized to a nonzero default (e.g. `contestBond = 1`) checked with `== 0` [E5](https://bugbountylibrary.com/r/c4%3A2024-03-taiko%3AM-02.md)
- Signed amounts accepted without a non-negative check, later fed to constructors that panic on negatives [E2](https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3.md)
- Batch loops validating only an aggregate sum, letting per-element zero through [E7](https://bugbountylibrary.com/r/sherlock%3A2024-01-looksrare%3AH-2.md)
- Spec special-cases ("result is 1") applied per-element vs aggregate across clients [E3](https://bugbountylibrary.com/r/cantina%3Aethereum_pectra_protocol_specification%3A3.1.1.md)

## How to review
The invariant: every sentinel must be distinguishable from all valid inputs at every read site, and every guard must compare against the value actually stored at that point. For each sentinel, list where it is written and where it is compared; confirm the same representation is used. For skip-branches, confirm downstream logic uses the same asset the check was skipped for [E1](https://bugbountylibrary.com/r/sherlock%3A2025-05-dodo-cross-chain-dex%3AH-2.md). For "max" sentinels, trace the zero case [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-17.md). For default-initialized fields, cross-check the initializer against equality guards [E5](https://bugbountylibrary.com/r/c4%3A2024-03-taiko%3AM-02.md). For signed amounts, confirm non-negativity before any coin/amount constructor [E2](https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3.md).

## Variants seen
- Sentinel address skips payment but message targets a real token [E1](https://bugbountylibrary.com/r/sherlock%3A2025-05-dodo-cross-chain-dex%3AH-2.md)
- Negative amount passes balance check, panics in EndBlocker [E2](https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3.md)
- Infinity-point special case applied inconsistently across clients [E3](https://bugbountylibrary.com/r/cantina%3Aethereum_pectra_protocol_specification%3A3.1.1.md)
- Max sentinel resolves to zero shares and zero assets [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-17.md)
- Nonzero default breaks `== 0` assert [E5](https://bugbountylibrary.com/r/c4%3A2024-03-taiko%3AM-02.md)
- Sentinel lender address breaks `sender == lender` [E6](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1.md)
- Zero deposit passes modulo and sum checks [E7](https://bugbountylibrary.com/r/sherlock%3A2024-01-looksrare%3AH-2.md)
- Two sentinels for native ETH, guard matches the wrong one [E8](https://bugbountylibrary.com/r/sherlock%3A2023-02-notional%3AM-4.md)

## Impact and severity
Drained accumulated tokens [E1](https://bugbountylibrary.com/r/sherlock%3A2025-05-dodo-cross-chain-dex%3AH-2.md), chain halt [E2](https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3.md), consensus split and slashing [E3](https://bugbountylibrary.com/r/cantina%3Aethereum_pectra_protocol_specification%3A3.1.1.md), blocked migration or loan closure [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-17.md)[E6](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1.md), corrupted winner selection [E7](https://bugbountylibrary.com/r/sherlock%3A2024-01-looksrare%3AH-2.md). Severity rises when the sentinel guards a fund-transfer skip or a consensus-critical path.

## Why fixes fail
Fixing one comparison site leaves others reading the same slot directly [E6](https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1.md); normalizing to one sentinel in the constructor without updating initialize guards leaves the mismatch [E8](https://bugbountylibrary.com/r/sherlock%3A2023-02-notional%3AM-4.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2025-05-dodo-cross-chain-dex%3AH-2.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3.md
- E3: https://bugbountylibrary.com/r/cantina%3Aethereum_pectra_protocol_specification%3A3.1.1.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-17.md
- E5: https://bugbountylibrary.com/r/c4%3A2024-03-taiko%3AM-02.md
- E6: https://bugbountylibrary.com/r/sherlock%3A2024-04-teller-finance%3AH-1.md
- E7: https://bugbountylibrary.com/r/sherlock%3A2024-01-looksrare%3AH-2.md
- E8: https://bugbountylibrary.com/r/sherlock%3A2023-02-notional%3AM-4.md
