# Unverified_667d: unprotected grantRole enables adminWithdraw drain

Unprotected grantRole on a BSC contract let the attacker self-assign the admin role, then call adminWithdraw to drain ~10.4k DAI.

- Payout: Real-world hack
- Severity: high
- Program: Unverified_667d
- Credited: DeFiHackLabs
- Disclosed: 2024-08-28
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-08/unverified_667d_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240828-unverified-667d
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm technique:source-review vuln:access-control vuln:auth-bypass

**Target:** BSC smart contract with role-based access control
**Root cause:** The grantRole(bytes32,address) function lacked access control, allowing any caller to grant themselves the admin role (bytes32(0)).
**Steps:**
1. Call `grantRole(bytes32(0), address(this))` on vul_addr 0x8DE7EAbA58EfB23B6F323984377af582B23134e9 from attacker contract
2. Call `adminWithdraw(header_addr, dai, attacker, 10463638549999999999999)` to transfer DAI to attacker
**Exploitation:** Attacker contract self-granted admin role via unprotected grantRole, then invoked adminWithdraw to move ~10,463 DAI from the contract to the attacker EOA in a single transaction.
**Insight:** On role-based contracts, check whether grantRole/initialize/setter functions are externally callable without onlyRole/onlyOwner guards; a single missing modifier on a role-granting function collapses the entire permission model.
