# `VaultAccountSecondaryDebtShareStorage.maturity` will be cleared prematurely

Liquidation path passes an uninitialized PrimeRate for the untouched secondary currency, zeroing its debt in memory and clearing account maturity, permanently blocking settlement.

- Payout: Contest reward
- Severity: high
- Program: Notional
- Credited: xiaoming90 + 0xleastwood
- Disclosed: 2023-03-09
- Write-up quality: 8/10
- Original: https://github.com/sherlock-audit/2023-03-notional-judging/issues/183
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-03-notional%3AH-3
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:liquidation

**Target:** VaultSecondaryBorrow / VaultLiquidationAction secondary borrow accounting
**Root cause:** _reduceAccountDebt only populates pr[currencyIndex-1], leaving the other PrimeRate zero; readDebtStorageToUnderlying then returns 0 for the untouched currency's debt, so _setAccountMaturity sees both debts as zero and clears maturity while real debt remains.
**Steps:**
1. Account has secondary debt in both currencies (e.g. accountDebtTwo=100) at maturity M.
2. Liquidator calls deleverageAccount (or liquidateVaultCashBalance) with currencyIndex=1.
3. _reduceAccountDebt builds `PrimeRate[2] pr; pr[0]=primeRate;` leaving pr[1] zero, calls updateAccountSecondaryDebt with netUnderlyingDebtTwo=0.
4. updateAccountSecondaryDebt: `accountDebtTwo = readDebtStorageToUnderlying(pr[1]=0, M, 100)` returns 0; accountDebtOne reduced to 0 via netUnderlyingDebtOne.
5. _setAccountMaturity sees both zero, sets `accountStorage.maturity = 0` while accountDebtTwo storage stays 100.
6. Later settleSecondaryBorrow reverts at `require(accountDebtOne==0 && accountDebtTwo==0)` since storedMaturity==0 but debtTwo!=0; account cannot settle or exit.
**How found:** Code-reading of _reduceAccountDebt: noticed the comment claiming the other prime rate is unused because net debt is zero, then traced that updateAccountSecondaryDebt still reads the untouched currency's stored debt through the zero PrimeRate, producing a false zero.
**Exploitation:** Any liquidator triggering deleverageAccount/liquidateVaultCashBalance on a vault account with debt in both secondary currencies corrupts the account's maturity to zero, bricking settlement and trapping user assets; no capital beyond a liquidation call needed.
**Insight:** When a helper zeroes a 'net change' argument, check whether downstream code still reads existing state through the omitted parameter — a zeroed rate/price used for conversion silently zeroes stored balances and can trip invariant-clearing branches.
