$1,000,000 in security audit grants are live now, Apply here →

← Resource Hub

Legacy Smart Contract Risk: How to Retire Old Deployments

By the Guardian team Updated 5 min read

Legacy Smart Contract Risk: How to Retire Old Deployments

Quick answer. Inventory every contract you have deployed, on every chain, with its owner, balances and approvals. Drain or migrate what still holds value, revoke what you can, and monitor the rest against advisories for its code and compiler.

Watch: Legacy Smart Contract Risk: How to Retire Old Deployments 1:40
Video transcript

Old contracts do not retire when your team moves on. If they still hold funds, minting rights or approvals, they are still attack surface.

Aztec Connect, deprecated in 2023, lost about 2.19 million dollars. An old Truebit contract overflowed, losing 26.2 million dollars, per Rekt.

Old code still holds value, was built to older standards, and often nobody can fix it. And bugs wait. Decurity says the 1inch Fusion bug was live for over two years.

Start from what you deployed, not your docs. Walk every deployer and factory address on every chain, record who controls each contract, then rank by exposure.

Then match the action to what each contract still has. Drain or migrate funds, revoke minting roles on every chain, and for approvals, disable entry points you control.

Renounce last, since it removes the pause too. Aztec Labs renounced in 2024, and in June 2026 the contracts still held funds nobody could pause.

Old code also inherits new disclosures. The Vyper post-mortem says affected protocols were not explicitly notified. So match every advisory against your inventory, and watch old addresses onchain.

Guardian's Managed Security keeps that inventory for you. Guardian also matches new disclosures against your system in real time and monitors your contracts on every block.

Read the full guide, or talk to Guardian about the contracts you forgot you deployed.

Old contracts do not retire when a team moves on. If they still hold funds, minting rights or user approvals, they are still attack surface.

They are often the least watched part of a protocol. Nobody on the team remembers them well, and sometimes nobody can pause them.

This guide covers why attackers hunt old code, how to build an inventory, and how to drain, pause, migrate or watch what you find.

Why Attackers Hunt Old Code

Five public incidents show the pattern:

IncidentWhat was oldWhat happened
Aztec Connect, June 2026Deprecated in 2023; control renounced April 2024About $2.19M in the first attack; no way to pause it
Truebit, January 2026A 2021 contract without automatic overflow checksAn overflow priced TRU near zero; $26.2M, per Rekt
1inch Fusion v1, March 2025Deprecated in mid-2023 but left deployedA resolver that never updated was drained
OKX DEX, December 2023A deprecated proxy still able to spend user approvalsAbout $2.7M of approved tokens taken, per PeckShield
Curve pools, July 2023Pools compiled with Vyper 0.2.15 to 0.3.0Broken reentrancy locks, fixed in Vyper but not in the pools

At Aztec Connect, the settlement code acted on fewer rows than the proof checked. Aztec Labs says the attacker got balances credited without real deposits.

At 1inch, Decurity says Fusion v1 "was not destructed for the purpose of backwards compatibility." Rekt puts the loss at about $5M, most of it later returned.

At OKX DEX, a deprecated contract was upgraded on December 12, 2023, and used to pull tokens users had approved. SlowMist suspected a leaked admin key.

Old code draws attackers for four reasons:

  • It still holds something: balances, minting rights or user approvals.
  • It was built to older standards: older compilers, libraries and tests.
  • Often nobody can fix it: Aztec Labs says it "holds no control over these contracts."
  • Bugs wait: Decurity says the Fusion v1 bug was live for more than two years.

Build a Contract Inventory

Start from what you deployed, not from what your docs describe. Walk every deployer and factory address, on every chain you have used.

For each contract, record:

  • Address, chain and deployment date.
  • Owner, admin and every privileged role, with who holds each.
  • Upgrade path: proxy admin, timelock, or immutable.
  • Balances it holds, and tokens it can mint or release.
  • Approvals users and other contracts have granted it.
  • What trusts it: peers, routers, resolvers and integrators.
  • Compiler version, settings, libraries and source.
  • The last audit that covered this exact bytecode.

Then rank by exposure: value held, value reachable through approvals, and who can still change it.

Inventories surface surprises. In Abracadabra's MIMv2 migration, Guardian flagged extra operators to remove on other chains, including duplicate Multichain minter rights on Moonriver (Low).

Drain, Pause or Migrate

Match the action to what each contract still has:

What it still hasWhat to do
Funds you can moveDrain or migrate them, then confirm a zero balance
Funds you cannot moveWarn users with dates, and monitor the contract
User approvalsDisable entry points you control; ask users to revoke
Minting or release rightsRevoke roles and remove peers on every chain
Admin keysKeep them safe until nothing of value remains

Retiring a contract is a change like any other, and it fails in the details. Guardian's public migration reviews show where:

  • USDT0, Corn delisting: queued transactions left Corn and Rootstock able to send on routes meant to close (Low).
  • USDT0, Arbitrum upgrade: in-flight bridges through the legacy gateway would have lost funds without a refund path (Low).
  • Olympus: deactivating the bridge stopped outbound sends but not inbound mints (Info).
  • Veranta: delegates stored by the old version kept cancel rights after the upgrade (Medium).

Renounce last. Renouncing removes the pause along with the upgrade.

Aztec Labs renounced control in April 2024, after a year of notice to users. In June 2026 it still held funds, and Rekt notes it could no longer be paused.

Continuous Advisory Matching

Old code inherits new disclosures. A compiler or library bug published today can apply to bytecode deployed years ago.

Solidity publishes a list of known compiler bugs by version, and its docs say verification tools should consult it.

A contract built with a buggy compiler after a fixed version was out is, in the docs' words, "highly suspicious".

The Vyper bug shows the gap. Its post-mortem says "the impact to protocols using the vulnerable compilers was not realized at the time and they were not explicitly notified."

So match every advisory against the inventory: compiler, libraries, forked code and integrations. Our guide to Solidity compiler bugs shows how one looks.

Then watch old addresses onchain: balance changes, role changes, upgrades and calls to functions nobody should use.

If you revive or patch an old contract, treat it as new code. See when you need a re-audit.

How Guardian Helps

Managed Security keeps a contract inventory: every address you have deployed, on every chain, with its owner and upgrade path.

It also tracks whether the code running today is the code that was reviewed.

Guardian ingests vulnerability disclosures in real time and matches them against your system. Where one reaches you, an engineer confirms the exposure and works with you on the patch.

Guardian monitors your contracts on every block for role and ownership changes, upgrades and large fund movements.

Migrations and network delistings can be verified before they run, as in Guardian's USDT0 deployment verification work.

Frequently Asked Questions

What is legacy smart contract risk?

The risk from deployed contracts a team no longer maintains but that still hold funds, minting rights or user approvals. They run old code, often cannot be paused, and are rarely monitored.

Can a deprecated contract still be exploited?

Yes. Aztec Connect, deprecated in 2023, lost about $2.19M in its first attack in June 2026. 1inch's Fusion v1, deprecated in mid-2023 but left deployed, was exploited through a resolver contract in March 2025.

Should we renounce ownership of old contracts?

Only after draining funds, revoking roles and peers, and warning users. Renouncing removes the ability to pause or upgrade, so an immutable contract that still holds value cannot be defended.

How do I find contracts my protocol has forgotten?

Start from every deployer and factory address on every chain. List what each deployment holds, who controls it and what still trusts it, then compare that list with your docs and monitoring.

Sources

Find the contracts you forgot you deployed

Guardian maps every address you have deployed, matches new advisories to its code, and watches it on every block.