# Incorrect updateGlobalExchangeRate implementation

Covalent DelegatedStaking: disableValidator/unstake can drive totalGlobalShares to zero, causing updateGlobalExchangeRate to lock accrued reward tokens permanently in the contract.

- Payout: Audit contest
- Severity: medium
- Program: Covalent
- Found by: xYrYuYx
- Disclosed: 2021-11-19
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-10-covalent-findings/issues/17
- Library page: https://bugbountylibrary.com/r/c4%3A2021-10-covalent%3AM-02
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** DelegatedStaking.sol staking/reward accounting contract
**Root cause:** updateGlobalExchangeRate mishandles the totalGlobalShares==0 case; disableValidator and unstake both subtract from global shares, so shares can reach zero while reward tokens remain undistributed.
**Steps:**
1. Deploy DelegatedStaking via Hardhat test (C4_issues.js L76)
2. Stake, then call `disableValidator` (callable by validator or owner) to reduce totalGlobalShares to 0
3. Mine 10 blocks plus 4 more via other function calls accruing ~14 CQT rewards
4. Observe rewards remain stuck in contract with no shares to distribute to
**How found:** Warden reasoned about the zero-share edge case in updateGlobalExchangeRate and constructed a Hardhat test disabling a validator to force totalGlobalShares to zero, then measured locked rewards.
**Exploitation:** Owner or colluding validators disable/unstake all shares to zero, then subsequent block rewards accrue with no share holders, permanently locking reward tokens in the contract.
**Insight:** In staking/reward contracts, test the invariant totalShares==0 after every share-reducing path (unstake, validator disable) and check whether reward accrual still credits a now-empty share pool.
