# The logic of _isUnderlying() in NotionalTradeModule is wrong which will cause mintFCashPosition() and redeemFCashPosition() revert on fcash tokens which asset token is underlying token (asset.tokenType == TokenType.NonMintable)

NotionalTradeModule._isUnderlying misclassifies non-mintable fCash (asset==underlying) as underlying, routing mint/redeem through useUnderlying=true and reverting all trades.

- Payout: Contest reward
- Severity: medium
- Program: Notional
- Credited: unforgiven
- Disclosed: 2022-07-18
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-06-notional-coop-findings/issues/87
- Library page: https://bugbountylibrary.com/r/c4%3A2022-06-notional-coop%3AM-03
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** NotionalTradeModule / wfCash integration (Set Protocol)
**Root cause:** _isUnderlying checks _paymentToken == underlyingToken first; for fCash where asset.tokenType == NonMintable, getUnderlyingToken() returns the asset token, so the check wrongly returns true and forces useUnderlying=true, which NotionalV2 rejects.
**Steps:**
1. Identify an fCash whose asset token is the underlying (asset.tokenType == TokenType.NonMintable).
2. Call mintFCashPosition()/redeemFCashPosition() with that fCash and its asset token as send/receive token.
3. Observe _isUnderlying returns true because _paymentToken == underlyingToken (asset==underlying).
4. _mint/_redeem select mintViaUnderlying/redeemToUnderlying selectors.
5. wfCashLogic calls NotionalV2 with useUnderlying=true, which reverts for non-mintable fCash; whole tx fails.
**How found:** Code-reading of _isUnderlying vs wfCashBase.getUnderlyingToken(); noticed getUnderlyingToken returns asset token when NonMintable, making the equality check ambiguous, then traced _mint/_redeem selector selection to NotionalV2 useUnderlying behavior.
**Insight:** When two token roles (asset vs underlying) can collapse to the same address, an equality-based branch that tests one role first silently misclassifies; check the distinguishing role (asset) or the tokenType flag rather than assuming roles are distinct.
