Orca Crypto
Menu
Start Here
Learn
Chains
Exchanges
Markets
Tools
Safety
Glossary
More
Our tokens Book a session
Advanced · Protocol risk

Upgradeability, admin keys and timelocks

Code is law only if the code cannot change. Here is how to find out who can change it, and how fast.

Loading live prices
By the Orca Crypto teamUpdated 2026-09-28How we check this10 min readAdvanced
The short answer

Most DeFi contracts can be changed. A proxy holds the funds and forward every call to an implementation contract whose address sits in a known storage slot, so whoever controls that slot controls the code. The questions that matter are who holds that power, how many keys it takes, and how long the delay is before a change takes effect. A timelock only protects you if it is longer than the time you need to exit.

Every protocol has a "who" and a "how fast"

Few DeFi protocols are entirely unchangeable, and for good reasons: bugs need fixing, parameters need tuning, markets need listing. So every serious protocol has powers held by someone. Your job as a user is to know, for each power, three things: who holds it, how many keys it takes, and how long between the decision and the effect.

PowerTypical holderWhat it can do to you
Upgrade the codeGovernance behind a timelock, or a multisigAnything at all, including moving deposits
Change parametersGovernance, risk stewards within boundsLiquidate you by lowering a threshold; change your rate
Change the oracleGovernance or an adminReprice your collateral
Pause or freezeA guardian multisigStop withdrawals or new borrowing for a while
Mint, freeze or blacklistThe token issuerDilute holders; freeze an address

None of these is bad in itself. A fast pause can save a protocol during an exploit; a slow upgrade gives users time to leave. The risk is in the combination: a powerful role, few keys, no delay.

How proxies make contracts upgradeable

Deployed bytecode cannot change. Upgradeability is an indirection: users talk to a proxy that holds all the storage and funds, and the proxy forward each call with delegatecall to an implementation contract. Delegatecall runs the implementation’s code against the proxy’s storage, so replacing one stored address swaps the logic while every balance stays put.

Transparent proxy

The upgrade functions live in the proxy. Calls from the admin can only upgrade; calls from everyone else always go to the implementation. OpenZeppelin’s version routes admin calls through a separate ProxyAdmin contract.

UUPS

The proxy is minimal and the upgrade function lives in the implementation, named after ERC-1822 (a proposal marked stagnant, though the pattern is widely used). Cheaper, but an implementation without a working upgrade function freezes the contract forever.

Beacon

Many proxies ask one beacon contract for their implementation. One transaction on the beacon upgrades every proxy at once, which is efficient and concentrates power accordingly.

OpenZeppelin’s proxy documentation compares the three in detail. Whatever the pattern, the practical question is identical: where is the implementation address stored, and who can write to it?

EIP-1967: where the implementation address lives

Early proxies each stored the implementation wherever they liked, which made them hard to inspect and prone to storage collisions with the implementation’s own variables. ERC-1967, created in 2019 and now final, standardizes the slots as hashes of fixed labels minus one, so no normal Solidity variable can land there and the preimage of the slot is unknown:

implementation slot = keccak256("eip1967.proxy.implementation") − 1
python
# EIP-1967 slots are hashes minus one (Python, pycryptodome)
from Crypto.Hash import keccak
def slot(label):
    h = keccak.new(digest_bits=256); h.update(label.encode())
    return hex(int(h.hexdigest(), 16) - 1)

slot("eip1967.proxy.implementation")
# 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
slot("eip1967.proxy.admin")
# 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
slot("eip1967.proxy.beacon")
# 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50

The standard also defines events (Upgraded, AdminChanged, BeaconUpgraded), which is why an explorer can show a full upgrade history and a "Read as Proxy" tab. You can read the slot yourself on any contract:

bash
# Read the implementation slot of any contract over JSON-RPC
curl -s -X POST "$RPC" -H 'content-type: application/json' --data '{
  "jsonrpc": "2.0", "id": 1, "method": "eth_getStorageAt",
  "params": ["<contract address>",
             "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
             "latest"] }'
# The last 20 bytes of the result are the implementation address.
# All zeros means "not an EIP-1967 proxy", which is not the same as "not upgradeable".

Two real cases show the limits of that check, both read in September 2026. Aave v3’s Pool on Ethereum stores its implementation in the EIP-1967 slot, but its admin slot is empty, because the admin is baked into the proxy’s bytecode as an immutable. And USDC’s proxy predates the standard: its EIP-1967 slot is empty and the implementation lives in an older OpenZeppelin (zeppelinos) slot. An empty slot tells you where not to look, nothing more.

Owners, admins, pausers and guardians

Beyond upgrades, contracts gate functions behind roles: an owner, an access control role, or a named guardian. Well designed systems make fast powers narrow and broad powers slow. Aave is a useful example: in April 2026, after an attacker deposited stolen rsETH as collateral, its Protocol Guardian began freezing rsETH markets across every deployment within about 90 minutes of the exploit, and a risk steward adjusted interest rate curves within preset bounds. Upgrading the protocol itself goes through governance.

Look for the same structure everywhere, including in your dependencies. The Chainlink ETH / USD feed proxy on Ethereum, which many protocols price collateral with, was owned by a 4 of 9 multisig as of September 2026. That is part of the trust you accept when a protocol reads it (see oracles).

Multisig thresholds and signer identity

An m of n multisig needs m signatures to act. It also has a second number people forget: how many keyholders it takes to block an action, which is n − m + 1.

SetupKeys to act (or steal)Keys to blockThreshold
2 of 32266.7%
3 of 53360.0%
4 of 94644.4%
5 of 95555.6%
9 of 129475.0%

The numbers are necessary and nowhere near sufficient. What matters is whether the keys are independent. The Ronin bridge required 5 of 9 validator signatures, but one organization controlled four validators and still held permission to sign for a fifth, so one compromise was enough (the Ronin post-mortem has the details). In the Bybit theft of February 2025, every signer approved what their interface showed as a routine transfer, and the transaction they actually signed replaced the wallet contract’s implementation. Same keys, same interface, same failure. The multisig guide covers setting one up; for protocols, ask who the signers are, whether they are publicly named, and whether they verify on independent hardware.

Timelocks and the exit window

A timelock is a contract that holds admin power and enforces a delay: an action is queued, becomes executable only after the delay, and expires if not executed within a grace period. Compound’s Timelock, which administers Compound v2 and the Compound III markets on Ethereum (markets on other chains take bridged proposals through their own local timelocks), enforces a minimum delay of 2 days, a maximum of 30 and a 14 day grace period; its delay was set to 2 days as of September 2026. Governance voting adds more days before anything is even queued.

real exit window = time from public queueing to execution − time you need to get out

The second term is where people fool themselves. Closing a leveraged loan, unwinding a liquidity position, or withdrawing from an optimistic rollup through its canonical bridge (about seven days) all take time. A 2 day timelock on a rollup bridge whose withdrawals take 7 days gives users no exit window at all: the upgrade lands while their funds are still in the pipe. A delay protects you only if it is longer than your exit, and only if someone is watching the queue. Services and bots that alert on queued transactions are what make a timelock useful in practice.

Check for the bypass
A timelock with an emergency bypass (a guardian or security council that can execute instantly) is only as slow as that bypass. Always ask what can skip the delay, and how many keys it takes.

Immutable contracts and their tradeoffs

The alternative is to give up upgrades. Morpho’s core lending contract is not a proxy: its owner can approve new interest rate models and liquidation LTVs and set a fee of at most 25% of interest, but no one can change a market’s oracle, collateral or parameters once it exists. Many protocols take the same route for their core and keep upgradeability only in the periphery.

Immutable core

No one can change the rules

  • No admin key to steal, bribe or coerce
  • What you audit is what runs, forever
  • A bug cannot be patched; users must migrate
  • Parameters cannot adapt to new markets

Upgradeable

Governance can change the rules

  • Bugs can be fixed before they are exploited
  • Risk parameters can respond to markets
  • Every user trusts the upgrade path
  • A compromised key can rewrite everything

Rollups: the L2BEAT stages

Layer 2s are the largest upgradeable contracts most users touch, because the canonical bridge holds the funds. L2BEAT’s stages framework grades how far control has moved from people to code. As published on its stages page in September 2026:

StageCore requirement
Stage 0Calls itself a rollup, posts state roots and data on L1, has open source software that can rebuild the state, and has a proper proof system (for fraud proofs, at least 5 external actors able to submit them)
Stage 1The only way (other than bugs) to indefinitely block a withdrawal or push an invalid one is to compromise at least 75% of the Security Council. Upgrades by anyone else must give users at least a 7 day exit window
Stage 2Permissionless fraud proofs, at least 30 days to exit before unwanted upgrades, and a Security Council limited to acting on bugs detectable onchain

L2BEAT also expects a Security Council of at least 8 publicly announced members, at least half from outside the core team, and since a January 2025 update it applies a high level guiding principle to Stage 1 that also bears on how short an optimistic rollup’s challenge period can be. As of September 2026 its listings put Base, Arbitrum One and OP Mainnet at Stage 1, while the few Stage 2 projects held little value. Two caveats from L2BEAT itself: stages measure decentralization, not freedom from bugs, and the requirements evolve (a December 2025 proposal would require the Stage 1 property to hold even if the Security Council went permanently inactive). The deeper mechanics are in rollup architecture, and the chains themselves on the layer 2 pages.

Checking all of this on a block explorer

  1. Is it a proxy?

    Open the contract on an explorer. A "Read as Proxy" tab or an implementation link means yes. Confirm by reading the EIP-1967 slot; if it is empty, check the docs for an older pattern before concluding anything.

  2. Who is the admin or owner?

    Call owner(), or read the admin slot, or find the ProxyAdmin. Follow the address: is it a person’s wallet, a multisig, a timelock or a governor?

  3. If it is a multisig, read it

    For a Safe, getThreshold() and getOwners() give the m and n. Then look for who the signers are in the protocol’s docs or governance forum.

  4. If it is a timelock, read the delay

    getMinDelay() on an OpenZeppelin TimelockController, delay() on a Compound style Timelock. Then check which roles can propose, execute or bypass it.

  5. Read the history

    Filter the contract’s events for Upgraded and admin changes. How often has the code changed, and did each change go through the delay? The guide on reading a transaction shows how to decode what each one did.

Common questions

What is a proxy contract?

A contract that holds the storage and funds but forward every call to a separate implementation contract using delegatecall. Changing the stored implementation address changes the logic without moving any funds, which is how most DeFi protocols upgrade.

Does an empty EIP-1967 slot mean a contract cannot be upgraded?

No. It means the contract is not a standard EIP-1967 proxy. Older proxies such as USDC’s use a different slot, and some contracts gate behavior behind roles without being proxies at all. Check the docs and the verified source.

How long should a timelock be?

Longer than the time users need to exit, with a margin for noticing. For simple deposits a few days can be enough. For positions that take a week to unwind, such as optimistic rollup withdrawals, a short timelock offers little real protection.

What is the difference between Stage 0, 1 and 2 on L2BEAT?

Stage 0 rollups are fully controllable by their operators. Stage 1 rollups can only be overridden by a Security Council supermajority, and other upgrades give a 7 day exit window. Stage 2 rollups have permissionless proofs, a 30 day exit window, and a Security Council limited to onchain detectable bugs.

Is an immutable protocol always safer?

It removes key risk, but a bug can never be patched, only escaped by migrating. Many teams choose an immutable core with upgradeable peripheral contracts to get most of both benefits.

Kept on this device only. Nothing is sent anywhere.

Where to go next

Next: Reading a transaction like an analyst

Guide 13 of 16 in the Advanced level. Your place is kept on this device, so you can pick up exactly here next time.

Share this page

Was this page useful?