# SubQuery Settings: unprotected setBatchAddress drains Staking SQT

Unprotected Settings.setBatchAddress let attacker become StakingManager and RewardsDistributor, draining 218M SQT from the Staking proxy.

- Payout: Real-world hack
- Severity: critical
- Program: SubQuerySettings
- Credited: DeFiHackLabs
- Disclosed: 2026-04-12
- Write-up quality: 8/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2026-04/SubQuerySettings_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20260412-subquerysettings
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** SubQuery Settings proxy / Staking proxy on Base
**Root cause:** Settings.setBatchAddress() had no access control, allowing anyone to overwrite the registered addresses of core contracts like StakingManager and RewardsDistributor. Staking trusted these addresses for authorization, so the attacker could impersonate them.
**Steps:**
1. Call `settings.setBatchAddress([StakingManager, RewardsDistributor], [attackerContract, attackerContract])` to become both dependency contracts.
2. As RewardsDistributor, call `staking.unbondCommission(address(this), drainAmount)` where drainAmount is the full SQT balance of the Staking proxy.
3. As StakingManager, call `staking.withdrawARequest(address(this), 0)` to withdraw the unbond request and receive the SQT.
4. Restore original addresses via `settings.setBatchAddress(ids, [originalStakingManager, originalRewardsDistributor])`.
5. Transfer drained SQT to attacker EOA.
**How found:** Likely identified that Settings.setBatchAddress lacked access control and that Staking relied on Settings for authorization of StakingManager and RewardsDistributor. By reading the contracts, the attacker saw they could impersonate those roles to drain funds.
**Exploitation:** Attacker called the unprotected setBatchAddress to replace StakingManager and RewardsDistributor with their own contract. Then, acting as RewardsDistributor, they created an unbond request for the entire SQT balance held by the Staking proxy. Next, acting as StakingManager, they withdrew that request, receiving the SQT. Finally, they restored the original addresses and transferred the funds to their EOA.
**Insight:** Look for unprotected setters in upgradeable proxy contracts that register dependency addresses; if downstream contracts trust those addresses for access control, you can impersonate critical roles and drain funds.
