# With most functions in VaultTracker.sol, users can call them only once after maturity has been reached.

VaultTracker stores post-maturity exchangeRate above maturityRate, causing uint underflow reverts that permanently block interest redemption and notional withdrawal.

- Payout: Contest reward
- Severity: medium
- Program: Swivel
- Credited: hansfriese
- Disclosed: 2022-09-29
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-07-swivel-findings/issues/116
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-swivel%3AM-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** VaultTracker.sol / Swivel.sol maturity accounting
**Root cause:** After maturity, removeNotional() overwrites vlt.exchangeRate with a value greater than market.maturityRate; subsequent functions compute maturityRate - exchangeRate and underflow.
**Steps:**
1. Alice calls `splitUnderlying()` to split 1000 USDC into zcToken and nToken
2. After maturity, call `combineTokens()`; this invokes `removeNotional()` which sets vlt.exchangeRate to a post-maturity rate > maturityRate
3. Call `redeemVaultInterest()`; reverts at VaultTracker.sol#L124 with uint underflow since maturityRate < vlt.exchangeRate
4. Alternatively redeem interest first, then `combineTokens()` reverts at VaultTracker.sol#L94 for the same reason
**How found:** Code reading of VaultTracker maturity math: noticed exchangeRate is monotonically increasing and can exceed maturityRate after removeNotional(), then traced subtraction sites for underflow.
**Exploitation:** No attacker; a user interacting directly with the contract (e.g. via Etherscan) past maturity triggers the state where exchangeRate exceeds maturityRate, permanently reverting their own redemption/withdrawal calls.
**Insight:** In maturity-based accounting contracts, check every subtraction of a stored rate against a snapshot rate for ordering assumptions; a monotonically increasing rate can invert the expected comparison after the snapshot is taken.
