The transparent proxy is the OpenZeppelin pattern that defined what mainstream contract upgradeability looked like for most of 2018 to 2022. It is no longer the default choice for new institutional deployments; UUPS replaced it (Part 3). But understanding the transparent proxy is non-negotiable for two reasons: a meaningful share of legacy production tokens still run on it, and the design choices it embodies are the reason UUPS exists at all. This part covers the architecture, the delegatecall mechanic that powers it, the admin separation that gives the pattern its name, and the gas trade-off that eventually pushed the field elsewhere.
Two contracts, one user-facing address
The pattern splits the contract in two. A proxy contract holds storage and the address of the implementation contract. An implementation contract holds the logic but no state. Users interact with the proxy. The proxy forwards every function call to the implementation using a low-level Ethereum opcode called delegatecall. Upgrades happen by changing the address the proxy points at, which leaves the proxy address (and therefore the user-facing address of the token) constant while swapping the underlying logic.
The user-facing constancy is the load-bearing property. A tokenised fund's holders, integrators, and counterparties have hard-coded the proxy address into custody allow-lists, transfer-agent records, exchange listings, and downstream protocol integrations. Asking them to migrate to a new address every time the fund needs a compliance update is operationally impossible. The proxy makes that constancy possible.
What delegatecall actually does
delegatecall is the EVM primitive that makes the pattern work. A normal call from contract A to contract B executes B's code in B's storage context: any state changes happen in B's storage, and B's address is what receives any payments. delegatecall is different. When A calls B via delegatecall, B's code runs but reads and writes A's storage, and the calling context (msg.sender, msg.value) is preserved as if the user had called A directly. The implementation behaves as if it were inlined into the proxy.
A short illustration of the dispatch logic at the heart of the proxy:
fallback() external payable {
address impl = _implementation();
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
Two consequences follow. First, the proxy must declare its storage layout in a way that matches the implementation, or else upgrades will silently corrupt state. Storage layout collisions are the single most common bug in proxy patterns, which is why OpenZeppelin and similar libraries publish strict storage-layout invariants and tooling to verify them across implementation versions. Second, the proxy and the implementation can be audited as separate units, which is operationally valuable: the proxy bytecode rarely changes, so its audit is durable, while the implementation can be re-audited on each upgrade.
The transparent part
The "transparent" in transparent proxy refers to a specific defence against function selector collisions. Both the proxy and the implementation are themselves Solidity contracts. The proxy needs admin functions of its own (upgradeTo, changeAdmin) and the implementation has its own functions (transfer, balanceOf, mint). If a function on the implementation happens to share a four-byte function selector with an admin function on the proxy, calls to that selector are ambiguous. Worse, an attacker could craft a payload that looks like a benign user transaction but routes to a privileged proxy function.
The transparent pattern resolves this by checking the caller on every invocation. If msg.sender is the admin address, the proxy answers admin functions itself and refuses to forward to the implementation. If msg.sender is anyone else, the proxy forwards everything to the implementation regardless of the function selector. The admin and the user populations are kept on strictly separate code paths.
This solves the collision problem. It also imposes a per-call gas cost: every single call to the proxy, no matter how trivial, runs the admin check before executing. For a payment token transferring billions of dollars across many small transactions, that overhead compounds. For a tokenised MMF whose transfers are infrequent and large, it is less material. The pattern was acceptable when gas was cheap and most institutional contracts saw low transaction volume; it became more painful as gas prices on Ethereum mainnet rose and as L2 deployments made every wei of overhead more visible by comparison.
Strengths and the operational reality
The transparent proxy's strengths are conservative ones. It is the most heavily audited upgradeable pattern in production. OpenZeppelin's implementation has been deployed and forked thousands of times, with the bugs found and fixed publicly. Custody providers, security firms, and auditors are uniformly familiar with the pattern, which lowers the friction of integrating a transparent-proxy-based token into the institutional stack. For an issuer evaluating contract risk, "this is a standard OpenZeppelin transparent proxy" is a meaningful statement that an auditor can attest to without bespoke review.
The weaknesses are also conservative ones. The gas overhead is real and measurable. The proxy contract itself is larger than it needs to be, which raises deployment cost. The admin separation, while sound, requires that the admin address never call user functions and never holds the underlying token, which complicates operational arrangements at issuers whose treasury and admin wallets sit close together. And the pattern offers no path to make the contract immutable later: once upgradeable, the proxy is upgradeable forever.
Where it survives in production
The transparent proxy is still common in DeFi protocols deployed before 2022 and in some early institutional tokenisation work. Most new tokenised fund deployments since 2023 default to UUPS instead, for the gas, size, and optional-immutability reasons Part 3 lays out. When a counterparty asks "what upgrade pattern are you using," the answer for a new institutional token in 2026 should almost always be UUPS, not transparent. The transparent proxy is the pattern you inherit, not the pattern you choose.