# Frontrunning validator freeze to withdraw tokens

Covalent's freeze mechanism is bypassable: transferUnstakedOut and recoverUnstaking lack the frozen check, letting a malicious validator unstake and withdraw after cooldown.

- Payout: Contest reward
- Severity: medium
- Program: Covalent
- Credited: PUSH0
- Disclosed: 2023-11-10
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-11-covalent-judging/issues/50
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-11-covalent%3AM-4
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:race-window technique:source-review vuln:access-control vuln:business-logic

**Target:** OperationalStaking.sol staking contract (transferUnstakedOut/recoverUnstaking)
**Root cause:** Most entry points require !v.frozen, but transferUnstakedOut() and recoverUnstaking() omit the frozen check, so an already-initiated unstaking can be withdrawn even after the validator is frozen.
**Steps:**
1. Validator accrues unfairly obtained rewards/stake.
2. Protocol submits freeze transaction for the validator.
3. Validator front-runs with a higher-gas `unstake()` (or simply unstakes before freeze lands).
4. Freeze executes; validator is now frozen but unstaking is recorded.
5. After cooldown, call `transferUnstakedOut(validatorId, unstakingId, amount)` — no frozen check — and receive tokens.
**How found:** Reviewer grepped for `require(!v.frozen, "Validator is frozen")` (6 occurrences) and eyeballed every external function, finding transferUnstakedOut() and recoverUnstaking() reachable without going through _stake()/_unstake() and thus missing the check.
**Exploitation:** Attacker monitors mempool for the freeze tx, submits unstake with higher gas to land first, waits out the 28-day cooldown, then calls transferUnstakedOut to withdraw stake and ill-gotten rewards; pausing the contract only locks everyone's funds and cannot revoke the pending unstaking.
**Escalation:** Judges noted front-running is not even required: any unstake initiated before freeze bypasses it, and no admin action can revoke a cooldown unstaking, so the only remedy is a contract upgrade.
**Insight:** When a protocol adds a global 'frozen/paused/blocked' guard, enumerate every external entry point and confirm each routes through the guarded internal helper; withdrawal/settlement functions that only move already-escrowed balances are the classic gap.
