★ delegatecall/call in proposal execution without allowlist
GMX v2 (GMX Synthetics)'s assessment for RD-F-039 — scored yellow on the v1.7.0 rubric. The evidence below is the curator's reasoning for this score.
Evidence summary #
GovTimelockController is OZ TimelockController using standard call (not delegatecall). ExternalHandler.sol makes arbitrary call(target,data) with no target allowlist — only checks target.isContract(). The direct governance execution path does not route through ExternalHandler, but if a governance proposal targets ExternalHandler or a CONTROLLER-role holder directs it, arbitrary contract calls are possible. No in-sample incident occurred, but the architectural design is a latent risk.
Sources #
- GitHubGovTimelockController sourceGovTimelockController.sol — thin wrapper over OZ TimelockController; uses standard call not delegatecallretrieved 2026-05-05
- Tally executed proposal — narrow scopeTally proposal (GMX Solana Treasury Swap) executed transfer() on specific token contract — narrow scope in practiceretrieved 2026-05-05
- ExternalHandler arbitrary callExternalHandler.sol — makeExternalCalls() accepts arbitrary target array, call(target, data), no allowlist, only target.isContract() checkretrieved 2026-05-05
Methodology #
Determine whether the governance executor contract uses `delegatecall` or `call` with proposal-supplied target, without enforcing an allowlist of permitted targets.
See the full factor methodology and distribution across all protocols →