# It's impossible to writing off any vouch fully for an outside actor

Union Finance debtWriteOff reverts when fully writing off a vouch because cancelVouch restricts callers to staker/borrower, leaving zombie dust vouches that bloat gas.

- Payout: Contest reward
- Severity: medium
- Program: Union Finance
- Credited: hyh
- Disclosed: 2022-11-04
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2022-10-union-finance-judging/issues/40
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-10-union-finance%3AM-13
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:access-control vuln:business-logic vuln:dos

**Target:** UserManager.sol debtWriteOff/cancelVouch
**Root cause:** debtWriteOff is publicly callable after overdue thresholds but internally calls cancelVouch, which only permits staker or borrower as msg.sender, so third-party full write-offs revert.
**Steps:**
1. Wait until `block.number > lastRepay + overdueBlocks + maxOverdueBlocks` so debtWriteOff is public.
2. Call `debtWriteOff(staker, borrower, amount)` as a non-staker/non-borrower with `amount == vouch.trust`.
3. Observe vouch.trust becomes 0, triggering `cancelVouch(staker, borrower)` internally.
4. cancelVouch reverts with AuthFailed since msg.sender is neither staker nor borrower.
5. Workaround: call with `amount = vouch.trust - dust`, leaving a zombie vouch open forever.
**How found:** Code reading of debtWriteOff's public-call branch versus cancelVouch's stricter access control, spotting the mismatch when trust hits zero.
**Escalation:** Accumulating zombie dust vouches increases gas in getCreditLimit, getFrozenInfo, borrow, repayBorrow; long-term could breach gas limits and freeze funds.
**Insight:** When a function relaxes access control for a public path, audit every internal call it makes for stricter modifiers that will revert on the same public caller.
