# An Oracle Signer can never be removed even if he becomes malicious

GMX Timelock's removeOracleSignerAfterSignal computes the add-signer action key instead of the remove-signer key, so removal always reverts.

- Payout: Contest reward
- Severity: medium
- Program: Gmx
- Credited: Chinmay
- Disclosed: 2023-04-20
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-04-gmx-judging/issues/205
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-04-gmx%3AM-6
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Timelock.sol removeOracleSignerAfterSignal (Solidity smart contract)
**Root cause:** removeOracleSignerAfterSignal calls _addOracleSignerActionKey(account) instead of _removeOracleSignerActionKey(account), so the computed actionKey (keccak256 of "addOracleSigner", account) never matches the pending action stored by signalRemoveOracleSigner (keccak256 of "removeOracleSigner", account).
**Steps:**
1. TimelockAdmin calls `signalRemoveOracleSigner(account)`, storing timestamp under actionKey = keccak256("removeOracleSigner", account) in pendingActions.
2. TimelockAdmin calls `removeOracleSignerAfterSignal(account)`.
3. Function computes `bytes32 actionKey = _addOracleSignerActionKey(account)` = keccak256("addOracleSigner", account).
4. `_validateAndClearAction(actionKey, "removeOracleSigner")` reads pendingActions[actionKey] which is zero, so validation reverts.
5. Removal can never succeed; fix is to call `_removeOracleSignerActionKey(account)`.
**How found:** Code reading of the two-stage signal/execute flow: noticed the execute function used the add-signer action key helper rather than the remove-signer helper, making the hash comparison structurally impossible to satisfy.
**Insight:** In two-stage timelock signal/execute patterns, verify that the execute path recomputes the action key with the exact same helper and string literal as the signal path; copy-paste of a sibling helper (add vs remove) silently bricks the action.
