{"id":"ERC-1967","name":"Proxy Storage Slots","status":"Final","chain":"both","category":{"id":"infrastructure","name":"Infrastructure","description":"Foundational patterns enabling other standards"},"journeyStages":[{"id":"infra","name":"Infrastructure","description":"Foundational patterns"}],"uxImpact":"ERC-1967 defines storage slots for a proxy's implementation, beacon, and admin information. Tools can resolve supported proxies and show the code they delegate to. Discover actual upgrade authority and source verification separately; standard slots do not establish safe code or universal explorer support.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-1967","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-1967","summary":"ERC-1967 defines storage slots for a proxy's implementation, beacon, and admin information. Tools can resolve supported proxies and show the code they delegate to. Discover actual upgrade authority and source verification separately; standard slots do not establish safe code or universal explorer support.","applicability":{"whenToUse":["Your product explains proxy implementations or upgrade authority.","An explorer needs to resolve a supported proxy pattern."],"whenToAvoid":["You cannot identify the proxy pattern or authorization path; show unknown instead of a safety claim.","You need ERC-1967 alone to prove an upgrade is safe or irrevocably disabled."]},"designerTakeaways":["Label proxy and resolved implementation addresses separately.","Use standard storage slots when the contract follows ERC-1967, and show unknown when resolution fails.","Explain verified upgrade authority and relevant changes without treating a resolved address as an audit."],"problemsSolved":[{"problem":"Block explorers show proxy bytecode, not real functions","oldWay":"User sees confusing proxy code, can't interact","newWay":"Explorer detects proxy, shows implementation interface","impact":"critical"},{"problem":"Can't verify what code proxy is running","oldWay":"Trust that proxy points to claimed implementation","newWay":"Standard slot, anyone can verify implementation address","impact":"critical"},{"problem":"Different proxies store implementation differently","oldWay":"Each proxy pattern needs custom detection","newWay":"Tools that support these slots can resolve compatible proxies with a shared lookup path.","impact":"high"},{"problem":"Admin address hidden or unpredictable","oldWay":"Who can upgrade this? Check code manually","newWay":"The optional admin slot is one clue; determine the actual authorization path for this proxy pattern","impact":"high"}],"uxPatterns":[{"name":"Block Explorer Proxy View","description":"A proxy-aware explorer resolves a supported implementation and uses its verified ABI when available.","userFlow":["User visits proxy contract on explorer","Sees \"This is a Proxy Contract\" banner","Views implementation address","Sees the verified upgrade authority for this proxy pattern, or an unknown state","Clicks \"Read as Proxy\" for real functions","Interacts with actual interface"]},{"name":"Contract Upgrade Notice","description":"Inform users about proxy upgrade","userFlow":["Protocol upgrades implementation","Users notified of change","See what changed (new features/fixes)","Review the new implementation, authority and potential effect on assets","Can verify upgrade transaction"]},{"name":"Proxy authority inspection","description":"Show the implementation, source verification, and actual control path with unknown states.","userFlow":["Identify the supported proxy pattern","Read the implementation slot or resolve the beacon","Show source verification and any version-specific audit as separate evidence","Resolve upgrade authority from the actual contract logic","Explain what was checked and any unresolved control or dependency risks"]},{"name":"Upgrade Governance","description":"An optional upgrade-management flow for a deployment whose governance integration exposes these operations.","userFlow":["Identify current upgrade authority and permitted action","Review implementation, initialization data, and supported compatibility checks","Submit through the deployed authorization mechanism","Show signer collection or timelock only if that governance system exposes it","Confirm execution and re-read the implementation"]}],"uiComponents":[{"name":"ProxyBanner","description":"Banner indicating contract is a proxy","states":["proxy-detected","not-proxy","unknown"],"props":["implementationAddress","adminAddress","proxyType"]},{"name":"ImplementationViewer","description":"Shows what implementation proxy points to","states":["loading","verified","unverified","error"],"props":["proxyAddress","implementationAddress","isVerified"]},{"name":"AdminAnalyzer","description":"Analyzes who controls proxy upgrades","states":["eoa","multisig","timelock","verified-no-upgrade-path","unknown"],"props":["adminAddress","adminType","signers[]","timelockDuration"]},{"name":"UpgradeNotification","description":"Alert showing contract was upgraded","states":["pending","executed","cancelled"],"props":["oldImplementation","newImplementation","changelog"]},{"name":"ProxyReadWrite","description":"Interface for interacting via proxy","states":["loading","ready","submitting"],"props":["proxyAddress","abiFromImplementation","onCall"]}],"antiPatterns":[{"pattern":"Showing proxy bytecode as \"contract source\"","why":"Users can't understand or verify what code runs","instead":"Detect proxy, show implementation source","severity":"critical"},{"pattern":"Hiding admin address","why":"Users don't know who can change the contract","instead":"Show the actual upgrade authority and permissions, including implementation or beacon roles","severity":"critical"},{"pattern":"No upgrade notifications","why":"Users surprised by changed behavior","instead":"Notify users when implementation changes","severity":"high"},{"pattern":"Single EOA as admin","why":"One compromised key = protocol compromised","instead":"Disclose the actual authorization policy. A single displayed admin address may be a contract, multisig, or timelock; do not infer key ownership from the address count.","severity":"high"},{"pattern":"Not linking to implementation on explorer","why":"User can't verify the actual code","instead":"Always provide clickable link to implementation","severity":"medium"}],"specConstraints":[{"id":"beacon-resolution","constraint":"A beacon must implement implementation(), whose result should not depend on the caller.","appliesTo":"infrastructure","normativity":"normative","specQuote":"The result of the `implementation()` function on the beacon contract SHOULD NOT depend on the caller (`msg.sender`).","specSection":"Specification > Beacon contract address","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#beacon-contract-address","designImplication":"Resolve beacon implementations consistently and identify unknown or caller-dependent results instead of presenting one universal implementation address."},{"id":"proxy-storage-integrity","constraint":"ERC-1967 storage slots must avoid compiler allocation and accidental overwrites; deliberate proxy-specific writes are required for changes.","appliesTo":"infrastructure","normativity":"security-considerations","specQuote":"## Security Considerations\n\nThis ERC relies on the fact that the chosen storage slots are **not** to be allocated by the solidity compiler. This guarantees that an implementation contract will not accidentally overwrite any of the information required for the proxy to operate. As such, locations with a high slot number were chosen to avoid clashes with the slots allocated by the compiler. Also, locations with no known preimage were picked, to ensure that a write to mapping with a maliciously crafted key could not overwrite it.\n\nLogic contracts that intend to modify proxy-specific information must do so deliberately (as is the case with UUPS) by writing to the specific storage slot.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#security-considerations","designImplication":"Show proxy, implementation, beacon, and upgrade authority separately and treat a resolved slot as a mechanism detail rather than an audit or safety guarantee."},{"id":"proxy-upgrade-monitoring","constraint":"Implementation and admin slot changes SHOULD emit corresponding events, including initialization from zero.","appliesTo":"application","normativity":"normative","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#specification","designImplication":"Show upgrade notifications from the corresponding implementation or admin events, including first initialization, and do not imply a change was observed when event data is missing.","specQuote":"Monitoring of proxies is essential to the security of many applications. It is thus essential to have the ability to track changes to the implementation and admin slots. Unfortunately, tracking changes to storage slots is not easy. Consequently, it is recommended that any function that changes any of these slots SHOULD also emit the corresponding event. This includes initialization, from `0x0` to the first non-zero value."},{"id":"logic-slot-resolution","constraint":"A proxy logic slot SHOULD be empty when a beacon is used, and changes to it SHOULD be reported through the corresponding event.","appliesTo":"infrastructure","normativity":"normative","specSection":"Specification > Logic contract address","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#logic-contract-address","designImplication":"Resolve a direct implementation only when the logic-slot state supports it, show unknown when the slot or event evidence is inconsistent, and refresh proxy status after an upgrade event.","specQuote":"Holds the address of the logic contract that this proxy delegates to. SHOULD be empty if a beacon is used instead. Changes to this slot SHOULD be notified by the event:"},{"id":"beacon-slot-resolution","constraint":"A proxy beacon slot SHOULD be empty when a logic address is used directly, should be considered only when the logic slot is empty, and changes SHOULD be reported through the corresponding event.","appliesTo":"infrastructure","normativity":"normative","specSection":"Specification > Beacon contract address","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#beacon-contract-address","designImplication":"Distinguish direct-logic and beacon resolution paths, do not display both as simultaneously authoritative, and refresh the resolved implementation after BeaconUpgraded.","specQuote":"Holds the address of the beacon contract this proxy relies on (fallback). SHOULD be empty if a logic address is used directly instead, and should only be considered if the logic contract slot is empty. Changes to this slot SHOULD be notified by the event:"},{"id":"beacon-client-resolution","constraint":"Clients SHOULD resolve a beacon proxy implementation by reading the beacon slot and calling implementation() on the beacon.","appliesTo":"infrastructure","normativity":"normative","specSection":"Specification > Beacon contract address","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#beacon-contract-address","designImplication":"For beacon proxies, show the implementation reached through the beacon path and distinguish an unresolved beacon from a direct logic-slot result.","specQuote":"Beacon based proxy contracts do not use the logic contract slot. Instead, they use the beacon contract slot to store the address of the beacon they are attached to. In order to know the logic contract used by a beacon proxy, a client SHOULD:"},{"id":"admin-slot-optional","constraint":"The ERC-1967 admin slot is OPTIONAL; when present, changes SHOULD be reported through the corresponding event.","appliesTo":"infrastructure","normativity":"normative","specSection":"Specification > Admin address","specUrl":"https://ercs.ethereum.org/ERCS/erc-1967#admin-address","designImplication":"Show admin as optional evidence, update authority displays when AdminChanged is observed, and never treat an absent admin slot as proof that upgrades are disabled.","specQuote":"Holds the address that is allowed to upgrade the logic contract address for this proxy (optional). Changes to this slot SHOULD be notified by the event:"}],"keyTakeaways":["ERC-1967 = standardized storage for proxy info","Compatible explorers can resolve the implementation and offer a proxy-aware interface.","Show the resolved implementation and actual upgrade authority; disclose unknowns","Warn users about admin trust assumptions","Notify on upgrades so users aren't surprised"],"technicalNotes":"ERC-1967 defines implementation, beacon and optional admin storage slots. Resolve a beacon proxy through its beacon to find the implementation. An admin slot can describe Transparent proxy administration, but UUPS upgrade authorization is implemented in the implementation contract, and beacon authority is separate. An empty admin slot does not prove that upgrades are disabled or ownership is renounced. Inspect the actual proxy pattern and authorization code before displaying control or safety claims.","lastUpdated":"2026-09-18","lastReviewed":"2026-09-18","sources":[{"label":"ERC-1967 official specification","url":"https://ercs.ethereum.org/ERCS/erc-1967","type":"official-spec"}]},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-1967","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-1967","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-1967","markdown":"https://www.eipsfordesigners.com/standards/ERC-1967/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-1967/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-1967","official":"https://ercs.ethereum.org/ERCS/erc-1967","discussion":"https://ethereum-magicians.org/search?q=ERC-1967"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}