# Adversary can arbitrarily trigger a chain halt by sending `MsgRemove{Delegate}Stake` with negative amount

Missing non-negative validation on MsgRemoveStake/MsgRemoveDelegateStake amounts lets anyone queue a negative stake removal that panics sdk.NewCoin in EndBlocker, halting the chain.

- Payout: Contest reward
- Severity: high
- Program: Allora
- Credited: Kow
- Disclosed: 2024-06-24
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-06-allora-judging/issues/21
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-06-allora%3AH-3
- Tags: domain:web3 impact:dos impact:mass-exploit kind:contest platform:sherlock sev:high tech:go technique:source-review vuln:business-logic vuln:dos

**Target:** Cosmos SDK emissions module msg server (RemoveStake/RemoveDelegateStake) and EndBlocker stake removal
**Root cause:** RemoveStake/RemoveDelegateStake accept signed integer Amount without a non-negative check; a negative amount also passes the staked-balance comparison. Later, stake_removals.go builds sdk.NewCoin(denom, negativeAmount), which panics inside the emissions EndBlocker.
**Steps:**
1. Send `MsgRemoveStake{Sender: addr, TopicId: 123, Amount: -1}` (or MsgRemoveDelegateStake) to the emissions msg server; it succeeds since no non-negative validation exists and the balance check passes.
2. Advance chain by `params.RemoveStakeDelayWindow` blocks.
3. At maturity, emissions EndBlocker calls RemoveStakes, which executes `sdk.NewCoins(sdk.NewCoin(DefaultBondDenom, stakeRemoval.Amount))` with the negative amount.
4. sdk.NewCoin panics on negative amount, aborting the EndBlocker and halting the chain.
**How found:** Code review of the stake removal flow: noticed Amount is a signed integer with no non-negative validation and that a negative value trivially passes the staked balance check, then traced the stored amount into EndBlocker's sdk.NewCoin call, which is known to panic on negatives.
**Exploitation:** Any account submits a single RemoveStake or RemoveDelegateStake message with Amount = -1 (no stake or capital required). After RemoveStakeDelayWindow blocks the queued removal is processed in the emissions module EndBlocker, where sdk.NewCoin panics on the negative value, permanently halting block production.
**Insight:** In Cosmos modules, trace user-supplied signed amounts from message handlers into EndBlocker/BeginBlocker paths where sdk.NewCoin/NewCoins panic on negatives; balance checks like `amount <= staked` do not reject negative values, so validation must be explicit.
