Upgradeable smart contracts are widely used in DeFi, NFTs, infrastructure protocols, and tokenized real-world assets.
Instead of deploying a completely new contract whenever the logic needs to change, developers can use a proxy pattern.
The proxy stores the user’s state while delegating execution to another contract containing the implementation logic.
There are several popular upgradeable proxy patterns, including:
Although all three rely on delegatecall, their upgrade mechanisms are significantly different.
One particularly interesting pattern is the Beacon Proxy, which is designed for a situation where many proxy contracts need to share the same implementation.
A real-world example can be found in Robinhood’s tokenized stock infrastructure, where official Stock Tokens on Robinhood Chain use Beacon Proxy contracts pointing to a shared Stock implementation.
A Beacon Proxy is an upgradeable proxy pattern where the proxy does not directly determine its implementation address.
Instead, it points to a separate Beacon contract.
The Beacon stores the current implementation address.
The architecture looks like this:
┌─────────────────────┐
│ UpgradeableBeacon │
│ │
│ implementation() │
│ ↓ │
│ Implementation V1 │
└──────────┬──────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ BeaconProxy A│ │ BeaconProxy B│
└──────┬───────┘ └──────┬───────┘
│ │
│ delegatecall │ delegatecall
│ │
└──────────┬───────────┘
▼
Implementation V1
Multiple proxies can therefore point to the same Beacon.
When the Beacon is upgraded from Implementation V1 to Implementation V2, all proxies using that Beacon automatically begin using the new implementation.
OpenZeppelin describes this as a pattern that allows multiple proxies to be upgraded to a different implementation in a single transaction.
The basic call flow is relatively simple.
Suppose a user calls:
proxy.transfer(to, amount);
The call reaches the BeaconProxy.
The proxy obtains the implementation address from the Beacon:
address implementation = beacon.implementation();
Then it delegates the call:
delegatecall(
implementation,
msg.data
);
Conceptually:
User
│
│ transfer(...)
▼
BeaconProxy
│
│ implementation()
▼
Beacon
│
│ returns Implementation V1
▼
Implementation V1
│
│ delegatecall
▼
Proxy Storage
The important part is that the implementation executes in the storage context of the proxy.
Therefore, each proxy can have its own:
while sharing the same implementation logic.
A Beacon Proxy architecture normally contains three components.
The proxy is the contract users interact with.
It forwards calls to the implementation returned by the Beacon.
In OpenZeppelin’s implementation, BeaconProxy retrieves its implementation from an UpgradeableBeacon.
The Beacon stores the current implementation address.
Conceptually:
contract Beacon {
address public implementation;
function upgradeTo(
address newImplementation
) external onlyOwner {
implementation = newImplementation;
}
}
The real OpenZeppelin UpgradeableBeacon also validates that the new implementation is a contract and restricts upgrades to its owner.
The implementation contains the actual business logic.
For example:
contract Stock {
function transfer(
address to,
uint256 amount
) external {
// token logic
}
}
The implementation does not normally store user-specific state for the proxy instances.
Instead, the code executes through delegatecall, meaning the proxy’s storage is modified.
The biggest advantage is mass upgrades.
Imagine a platform with 1,000 token contracts.
Without a shared Beacon, each proxy may need to be upgraded independently.
With a Beacon architecture:
Beacon
│
┌───────────┼───────────┐
│ │ │
Proxy 1 Proxy 2 Proxy 3
│ │ │
└───────────┼───────────┘
│
Implementation
Changing the Beacon implementation changes the implementation used by all connected proxies.
This is particularly useful when deploying many contracts with the same behavior.
Examples include:
OpenZeppelin specifically identifies tokens, NFT collections, DeFi protocols, and other systems with many instances as suitable use cases for Beacon Proxy.
The biggest difference is where the upgrade control lives.
A typical architecture looks like:
User
│
▼
Transparent Proxy
│
├── ProxyAdmin
│
└── Implementation
The ProxyAdmin controls the upgrade of the proxy.
Each proxy can have its own upgrade configuration.
For example:
Proxy A ──> Implementation A
Proxy B ──> Implementation B
Proxy C ──> Implementation C
Upgrading Proxy A does not automatically upgrade Proxy B or Proxy C.
Beacon architecture looks like:
Beacon
│
Implementation V1
/ | \
/ | \
Proxy A Proxy B Proxy C
If the Beacon changes to:
Implementation V2
then:
Proxy A ──┐
Proxy B ──┼──> Implementation V2
Proxy C ──┘
This is the key difference.
Upgrade proxies individually.
Upgrade many proxies through one shared Beacon.
UUPS stands for:
Universal Upgradeable Proxy Standard
UUPS has a different architecture.
The upgrade mechanism is implemented inside the implementation contract itself.
Conceptually:
Proxy
│
│ delegatecall
▼
UUPS Implementation
│
│ upgradeTo()
▼
New Implementation
The implementation contains the authorization logic for upgrades.
OpenZeppelin notes that UUPS proxies rely on an _authorizeUpgrade() function to restrict who can perform upgrades.
Beacon Proxy instead separates the upgrade mechanism into the Beacon.
UUPS:
Proxy
│
▼
Implementation
│
└── upgrade mechanism
Beacon:
Proxy ──────┐
Proxy ──────┼──> Beacon ──> Implementation
Proxy ──────┘
A simplified comparison looks like this:
| Feature | Transparent | UUPS | Beacon |
|---|---|---|---|
| Upgrade mechanism | Proxy/Admin | Implementation | Beacon |
| Multiple proxies share implementation | No | Not inherently | Yes |
| Mass upgrade | No | No | Yes |
| Upgrade authorization | ProxyAdmin | _authorizeUpgrade() | Beacon owner |
| Best use case | General upgradeable contracts | Gas-efficient individual proxies | Large numbers of similar contracts |
| Central upgrade point | ProxyAdmin | Each implementation/proxy | Beacon |
| Main risk | Admin compromise | Upgrade authorization | Beacon compromise |
The important point is that Beacon Proxy is not simply another version of UUPS.
It solves a different architectural problem.
One of the most interesting examples of Beacon Proxy usage is Robinhood Chain’s tokenized stock infrastructure.
Robinhood’s official documentation describes its Stock Tokens as standard ERC-20 tokens representing tokenized debt securities issued by Robinhood Assets (Jersey) Limited, providing economic exposure to underlying securities.
On Robinhood Chain, official stock token contracts can be observed using the BeaconProxy architecture.
For example, public contract data for Robinhood’s stock-token ecosystem shows BeaconProxy contracts and a shared Stock implementation.
This is a very natural use case for Beacon Proxy.
Imagine Robinhood supports hundreds of stock tokens:
AAPL
NVDA
TSLA
MSFT
GOOGL
AMZN
...
Each token needs its own state:
AAPL
├── balances
├── totalSupply
└── token-specific configuration
NVDA
├── balances
├── totalSupply
└── token-specific configuration
TSLA
├── balances
├── totalSupply
└── token-specific configuration
But much of the underlying logic can be shared.
Therefore, the architecture can conceptually look like:
Stock Beacon
│
▼
Stock Implementation
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
AAPL Proxy NVDA Proxy TSLA Proxy
│ │ │
▼ ▼ ▼
AAPL Storage NVDA Storage TSLA Storage
This gives the system a major operational advantage.
If the shared token implementation needs to be upgraded, the Beacon can be upgraded rather than upgrading every stock-token proxy individually.
Consider a platform with 500 tokenized stocks.
Suppose all tokens use the same basic ERC-20 implementation.
Without Beacon Proxy:
Upgrade AAPL
Upgrade NVDA
Upgrade TSLA
Upgrade MSFT
Upgrade GOOGL
...
That can become operationally expensive and error-prone.
With Beacon Proxy:
Beacon
│
├── AAPL
├── NVDA
├── TSLA
├── MSFT
└── GOOGL
One Beacon upgrade can change the implementation used by all of them.
This is exactly the kind of architecture where Beacon Proxy provides significant value.
The same feature that makes Beacon Proxy powerful also makes it dangerous.
The Beacon becomes a critical trust boundary.
Suppose there are 500 tokens:
Beacon
│
┌────────┼────────┐
│ │ │
AAPL NVDA TSLA
If an attacker gains control of the Beacon’s upgrade authority, the attacker may potentially change the implementation for every proxy.
For example:
Normal:
Beacon
↓
SafeImplementation
Compromised:
Beacon
↓
MaliciousImplementation
Now every proxy using that Beacon may execute malicious logic.
This is significantly different from a system where each proxy has an independent upgrade authority.
When auditing a Beacon Proxy architecture, one of the first questions should be:
Who can call
upgradeTo()on the Beacon?
For an OpenZeppelin UpgradeableBeacon, the upgrade function is restricted to the Beacon owner.
Therefore, auditors should investigate:
Who is the owner?
↓
EOA?
Multisig?
DAO?
Timelock?
Another contract?
Then ask:
The Beacon owner is therefore often one of the most important privileged roles in the entire system.
Beacon Proxy does not eliminate the normal storage-layout risks associated with upgradeable contracts.
For example:
contract StockV1 {
uint256 totalSupply;
address owner;
}
An upgrade must preserve compatible storage layout.
A careless implementation could introduce:
contract StockV2 {
address owner;
uint256 totalSupply;
}
Changing the order of variables can cause existing storage to be interpreted incorrectly.
This can potentially result in catastrophic accounting or authorization bugs.
OpenZeppelin’s upgrade tooling includes validation mechanisms intended to detect upgrade-safety and storage-compatibility issues.
When auditing a Beacon Proxy system, security researchers should inspect at least the following areas.
Check:
owner()
and determine exactly who controls upgrades.
Review:
upgradeTo(newImplementation)
Questions include:
Check whether the new implementation preserves:
Beacon proxies use initialization data rather than constructors for proxy-specific state.
Therefore, auditors should verify:
Ask:
How many proxies use this Beacon?
A vulnerability in the shared implementation may affect every connected proxy.
This creates a potentially much larger blast radius.
This is perhaps the most important security concept to understand.
Suppose:
Beacon
│
├── Token A
├── Token B
├── Token C
├── Token D
└── Token E
A vulnerability in the shared implementation may affect:
5 contracts
But in a production system with thousands of proxies:
Beacon
│
├── Proxy 1
├── Proxy 2
├── Proxy 3
├── ...
└── Proxy 1000
The blast radius can be enormous.
Therefore, when auditing Beacon Proxy systems, it is not enough to audit each proxy individually.
The auditor needs to understand the entire Beacon → Implementation → Proxy relationship.
Beacon Proxy provides an elegant solution for managing large numbers of upgradeable contracts.
But it introduces an important trade-off:
Operational efficiency
↑
│
│
▼
Centralized upgrade authority
A single Beacon can make upgrades dramatically easier.
At the same time, the Beacon becomes a critical component of the security model.
The security of hundreds of proxy contracts may ultimately depend on:
Beacon
↓
Beacon Owner
↓
Upgrade Authorization
↓
Implementation
If any part of this chain is compromised, the consequences can be significant.
Beacon Proxy is not simply another upgradeable proxy implementation.
Its main purpose is to solve a specific problem:
How can a system deploy many independent proxy contracts while allowing them to share the same implementation and upgrade them efficiently?
The answer is the Beacon Proxy pattern.
Compared with other common patterns:
The architecture is particularly useful for systems that create large numbers of similar contracts.
Robinhood’s tokenized stock infrastructure provides an interesting real-world example. Official Stock Tokens on Robinhood Chain use Beacon Proxy contracts and share common implementation logic, making the pattern relevant not only to DeFi developers but also to modern RWA and tokenization systems.
For security researchers, however, Beacon Proxy should immediately trigger another question:
Who controls the Beacon?
Because once hundreds of contracts depend on the same Beacon, the Beacon’s upgrade authority can become one of the most important security boundaries in the entire protocol.
When auditing a Beacon Proxy system, don’t stop at the proxy.
Trace the complete path:
Proxy
↓
Beacon
↓
Implementation
↓
Upgrade Authority
Understanding this architecture is essential for identifying both ordinary implementation bugs and high-impact upgrade-control vulnerabilities.
UNCX's token vesting contract lost roughly $87.7K when an attacker exploited a share-accounting flaw in release(), topUpVesting(), and cancel(). We break down the root cause, the exact attack sequence, and what builders should take away from it — without the jargon.
Autheo’s THEO token lost 92% after attackers used a Hyperlane TrustedRelayerIsm misconfiguration to mint 19 million unbacked tokens on Base and extract roughly $1.76 million. Here’s how the attack worked and why single-key security models remain dangerous for cross-chain assets.
Uniswap v4 hooks explained: the PoolManager singleton, flash accounting, and what the Cork and Bunni exploits teach us about hook security. A PandaSecurity deep dive.
An attacker forced a Uniswap V4 vault into a zero-liquidity state, redeemed one minimal share unit, and withdrew roughly 14,838.47 DAI. Panda Security breaks down the transaction, vulnerable code, root cause, and practical fixes.