Skip to main content
Sigvex

Function Selector Collision Remediation

Use a transparent proxy pattern or rename functions so admin and implementation selectors never collide.

Function Selector Collision Remediation

Overview

The EVM dispatches external calls using a 4-byte selector derived from the function signature. With only 2^32 selectors, collisions can be found by brute force. In a proxy, a collision between an admin/upgrade function and an implementation function means a call meant for one executes the other, potentially handing an attacker admin control or running user logic in the wrong storage context.

Related Detector: Function Selector Collision

Before (Vulnerable)

// Proxy admin and implementation share selector 0x12345678
// Proxy: function upgradeAdmin(address) -> 0x12345678
// Impl:  function collideFunc(address)  -> 0x12345678

After (Fixed)

import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

// The proxy routes calls by msg.sender:
//   admin  -> proxy admin functions
//   others -> delegated to implementation
// Admin and implementation selectors can never be reached by the wrong caller.

A transparent proxy decides whether to run proxy logic or delegate based on msg.sender. The admin address reaches admin functions; everyone else is always delegated to the implementation. This makes selector overlap between the two surfaces irrelevant, because the dispatch decision no longer depends on the selector alone.

Alternative Mitigations

  • If a non-proxy contract has two functions sharing a selector, rename one until the 4-byte selectors differ. Compute selectors during the build and fail the build on any duplicate.
  • For diamond (EIP-2535) deployments, enforce a registry check that rejects adding a facet function whose selector already exists.
  • Keep upgrade and admin functions on a separate contract from user-facing logic so their selector spaces never mix.

Common Mistakes

  • Relying on a UUPS or minimal proxy that dispatches purely by selector, which does not resolve admin/implementation collisions.
  • Assuming a collision is impossible because it is rare; selectors can be deliberately mined to collide.
  • Renaming a function to dodge a collision without checking that the new name does not collide with a third function.

References