GPT-5 finding
Factory keeps Timelock admin powers due to wrong role being renounced
criticalsecurityhigh
- src/governance/GovernanceFactory.sol
- src/governance/GovernanceFactory.sol
The TimelockController is created with admin set to the GovernanceFactory (msg.sender in TimelockFactory.create). The factory then renounces DEFAULT_ADMIN_ROLE (0x00), but TimelockController role admin for PROPOSER/EXECUTOR/CANCELLER is TIMELOCK_ADMIN_ROLE, not DEFAULT_ADMIN_ROLE. As a result, the factory retains TIMELOCK_ADMIN_ROLE and can grant/revoke roles or otherwise control the timelock, subverting governance security assumptions.
Recommendation
- Renounce TIMELOCK_ADMIN_ROLE instead: timelockController.renounceRole(timelockController.TIMELOCK_ADMIN_ROLE(), address(this)). - Preferably transfer TIMELOCK_ADMIN_ROLE to the timelock itself or to the governance contract before renouncing the factory’s admin, following OZ’s recommended pattern (self-admin or DAO-admin).