When two functions in the implementation contract have the same function selector, unintended functions can be called, leading to incorrect behavior or security loopholes
Game
This proxy implements a function with a selector that could potentially collide with implementation contract functions.
// SPDX-License-Identifier: MIT// Open me in VSCode and really think before opening the hints!// Add @audit tags wherever suspicious// Go to the solidity docs to complete missing knowledge of what's happening here// Solve by drafting a fix!// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;contract LogicContract {uint256public data;functionsetData(uint256_data) public { data = _data; }}contract ProxyContract {addresspublic implementation;constructor(address_implementation) { implementation = _implementation; }functionsetImplementation(address_implementation) public { implementation = _implementation; }// Fallback function that forwards calls to the implementation contractfallback() externalpayable { (bool success, ) = implementation.delegatecall(msg.data);require(success,"Delegatecall failed"); }}
The function selector is determined by the first four bytes of the hashed function signature.
Think about what happens if a call intended for LogicContract accidentally matches a function in ProxyContract.
Using a specific interface structure can help avoid accidental selector collisions between proxy and implementation.
Look into ways to segregate function selectors in proxy and implementation contracts.
contract ProxyContract {bytes32privateconstant implementationSlot =keccak256("proxy.implementation.address");constructor(address_implementation) {setImplementation(_implementation); }// Fix: setImplementation is now internal to block collisionsfunctionsetImplementation(address_implementation) internal {assembly {sstore(implementationSlot, _implementation) } }functiongetImplementation() publicviewreturns (address impl) {assembly { impl :=sload(implementationSlot) } }// Fallback function that forwards calls to the implementation contractfallback() externalpayable {address impl =getImplementation();require(impl !=address(0),"Implementation not set"); (bool success, ) = impl.delegatecall(msg.data);require(success,"Delegatecall failed"); }}