Upgradeable smart contracts can keep the same public address while changing the code that handles calls to it. In a proxy arrangement, users interact with the proxy; the proxy delegates work to a separate implementation.
That means a familiar address does not establish that the rules behind it are unchanged. To understand the trust involved, check how upgrades are authorised and which implementation is currently in use.
OpenZeppelin’s proxy documentation explains the mechanism. This guide follows that documentation’s concepts, rather than providing deployment code or claiming to have audited a particular contract.
Two contracts divide the work
A proxy is the entry point. An implementation contains the logic that the proxy uses.
An upgrade does not rewrite the deployed bytecode of either existing contract. It changes which implementation the proxy points to. A newly deployed implementation can therefore handle future calls through the existing proxy address.
The distinction answers the apparent contradiction between immutable deployed code and an upgradeable application. The individual contracts’ code can remain fixed while the relationship between them changes.
For a user, the important consequence is practical: an address bookmarked yesterday can execute different application logic after an authorised upgrade. Address continuity is useful for a system, but it is not evidence of permanent rules.
The state stays with the proxy
OpenZeppelin describes forwarding with the EVM’s delegatecall operation. The implementation’s code runs in the context of the proxy’s state.
This separates the place where persistent application data lives from the code that interprets it. The proxy holds the state, while the selected implementation supplies the logic for the delegated call.
An illustrative application might keep balances in the proxy’s storage while changing the implementation used for a particular operation. That does not mean every upgradeable contract is a token or that every upgrade changes balances. It explains why the compatibility of new logic with existing state matters.
Looking only at the implementation address can therefore miss part of the system. A reader needs to know which proxy is used, which implementation it delegates to and which state layout the implementation expects.
Upgrade authority is part of the trust
The documentation says upgrade control can be governed through an address, a multisignature wallet or a more complex governance arrangement. Those are different arrangements, and the label “upgradeable” does not identify which one a deployed application uses.
Check the actual authority for the specific proxy. Who can select a new implementation? What evidence identifies that authority? What process is documented for changing it?
A statement that an application has governance is insufficient on its own. The relevant question is what the deployed upgrade mechanism permits and how the claimed governance connects to it.
Likewise, the presence of several participants should not be translated into a guarantee that an upgrade is safe. Authority, review and the content of an upgrade are separate questions.
This is a different permission from an ordinary wallet signature. Our wallet-signature guide explains why a user’s authorisation also needs to be read for its actual effect.
Storage compatibility can break an upgrade
The proxy and implementation must avoid interfering with each other’s storage. OpenZeppelin’s unstructured-storage explanation uses specially chosen slots for proxy information, including the implementation pointer.
That addresses one kind of collision. It does not automatically make every future implementation compatible with the application’s existing storage.
Suppose a first implementation treats a storage location as an owner address. A new version that interprets the same location as a different value can read or overwrite existing state incorrectly. Changing the variable layout can therefore change what the same stored bytes mean.
OpenZeppelin’s documented guidance is to preserve the existing storage layout and extend it appropriately, rather than rearranging earlier variables. Its upgrades tooling can detect relevant storage collisions and warn developers.
A tool’s check is useful evidence about the checks it performs. It should not be stretched into a claim that the new logic has no security problems or that every possible behaviour was reviewed.
Initialisation is another separate step
A constructor runs when its own contract is deployed. The implementation’s constructor does not initialise the proxy’s storage as though the proxy had deployed that implementation’s code itself.
The documentation explains why upgradeable applications use an initializer for the relevant state setup. The initialisation function must be protected so it cannot simply run again and overwrite the established state.
For a deployed application review, ask how initialisation happened and what prevents an unauthorised repetition. A verified implementation source does not answer whether the proxy was initialised correctly.
Do not copy the page’s illustrative Solidity sample into a production deployment without checking the exact library version and current implementation guidance. This article explains the mechanism; it is not a production recipe.
Transparent proxies resolve a different problem
A proxy can expose administration functions as well as forwarding application calls. Function identifiers can clash between the proxy and implementation.
OpenZeppelin describes the transparent proxy pattern as using the caller’s identity to distinguish administration from normal delegated calls. In that described pattern, an administrator’s calls are handled as administration rather than delegated like ordinary user calls.
This is a particular design, not a definition of every proxy. Other systems can use different upgrade arrangements. A user should establish which design the application actually deploys before relying on its behaviour.
It also illustrates why “the source is verified” needs a precise object. Verified source for one implementation does not describe the entire proxy, administration and governance relationship by itself.
Read an application’s claim in layers
A useful review separates four questions:
| Layer | Evidence to look for |
|---|---|
| Entry point | The exact proxy address and network |
| Current logic | The implementation selected by that proxy |
| Upgrade authority | The deployed mechanism and who can operate it |
| Compatibility and setup | Storage checks, initialisation and the documented review process |
Then read the application-specific claims. Which behaviour is promised? Can an upgrade change it? Which evidence explains the current version?
If a provider describes a contract as immutable, establish what that statement covers. It may refer to fixed deployed bytecode while leaving an upgradeable proxy relationship outside the wording.
If it describes an upgrade as a bug fix, distinguish that explanation from evidence about the actual new logic. The purpose given by a team and the effect of deployed code are related but separate.
Source and documentation stamp
Checked 9 October 2026 against OpenZeppelin’s Proxy Upgrade Pattern documentation. The page describes unstructured storage, delegatecall, storage compatibility, initializers and transparent proxies; its code snippets are illustrative and include historical library references. This guide makes no claim about auditing, deploying or testing a live contract.





