Web3Exploit logoWeb3Exploit
← Back to Case Research

UPCX $70M Case Research: When a ProxyAdmin Key Became the Protocol

UPCX is not interesting because the attacker found a clever arithmetic bug. It is interesting because the on-chain system did exactly what the privileged key told it to do. The attacker reportedly gained control over an administrative address, used it to perform a malicious upgrade through ProxyAdmin, then executed withdrawByAdmin to drain 18.4M UPC, about $70M, from management accounts.

This reconstruction uses Halborn's April 2025 explanation, Cyvers/UPCX-linked reporting, and SmartContractsHacking/Incrypthos summaries. Public source for the exact upgraded implementation is limited, so the code below is representative of the upgrade pattern and privileged-drain primitive.

The takeaway: upgrade authority is protocol authority. If one compromised key can change implementation logic, every downstream access-control check can be rewritten after the compromise.

Target architecture: upgradeable control plane

Upgradeable proxies split contract state from contract logic:

Proxy
  storage + user-facing address
  delegates calls to implementation

ProxyAdmin
  privileged controller
  can upgrade proxy implementation

Implementation
  logic contract
  executes in proxy storage context

That design is normal. The risk is centralization: whoever controls ProxyAdmin can replace the contract's behavior.

Representative shape:

contract ProxyAdmin {
    address public owner;

    function upgrade(address proxy, address implementation) external onlyOwner {
        ITransparentUpgradeableProxy(proxy).upgradeTo(implementation);
    }
}

If owner is a single hot key, the entire protocol depends on that hot key.

Root cause: compromised upgrade authority

Public reporting frames the incident as a private-key compromise. The attacker gained access to a privileged project address and used the associated authority to upgrade the ProxyAdmin-controlled contract path.

The malicious implementation then exposed or used an admin withdrawal primitive:

contract MaliciousImplementation {
    IERC20 public immutable UPC;

    function withdrawByAdmin(address from, address to, uint256 amount) external {
        // After malicious upgrade, the implementation defines its own rules.
        // If this executes in the proxy's context, existing balances/allowances
        // and management-account bookkeeping can be drained.
        UPC.transferFrom(from, to, amount);
    }
}

The exact function shape may differ, but the security lesson does not: once the attacker controls the implementation, the original source-level guarantees are no longer the code being executed.

Attack chain

  1. Compromise a privileged administrative key. The public post-incident reports do not disclose the off-chain compromise vector, but the attacker had authority over the upgrade path.
  2. Execute a malicious upgrade. The attacker uses the privileged address to change the ProxyAdmin-controlled implementation.
  3. Expose a withdrawal primitive. The new logic includes or enables withdrawByAdmin.
  4. Drain management accounts. The attacker transfers 18.4M UPC from multiple management accounts.
  5. Leave funds parked. Public dashboards reported the funds remained in an attacker-controlled wallet shortly after the event.
  6. Protocol response. UPCX paused/froze deposits and withdrawals and moved remaining project-controlled tokens to safer addresses.

Representative execution:

// Step 1: attacker has the ProxyAdmin owner key.
proxyAdmin.upgrade(upcxProxy, maliciousImplementation);

// Step 2: same proxy address now executes malicious logic.
IUpcxBackdoor(upcxProxy).withdrawByAdmin(
    managementAccountA,
    attacker,
    18_400_000e18
);

This is why "audited implementation code" is not enough. The implementation can be replaced.

Why this bypasses normal smart-contract review

An audit can verify that version N of a contract has correct onlyOwner checks. It cannot protect users if:

  • the owner key is a single point of failure,
  • upgrades have no timelock,
  • users cannot monitor or exit before an upgrade takes effect,
  • the upgraded implementation is not subject to the same review path,
  • emergency controls are held by the same compromised authority.

The control-plane invariant should have been:

No single compromised credential can both change code and drain assets before detection.

UPCX appears to have violated that invariant.

Transaction and address trail

Public references identify:

  • Incident date: April 1, 2025
  • Loss: 18.4M UPC, roughly $70M
  • Technique: compromised administrative key, ProxyAdmin upgrade, withdrawByAdmin
  • Attacker destination described by SmartContractsHacking as 0xFf7...334
  • Primary public alert: https://x.com/CyversAlerts/status/1907046941906653633
  • UPCX acknowledgement: https://x.com/Upcxofficial/status/1907024397497749647

I am not treating the abbreviated attacker address as sufficient for precise forensic reproduction. It is included only to match public summaries.

What I would change

  1. Move ProxyAdmin authority to multisig or MPC. One key should never be enough to upgrade contracts that control treasury-scale assets.
  2. Timelock upgrades. Users and monitors need time to inspect new implementations before execution.
  3. Separate upgrade and withdrawal authority. The same role should not be able to both change logic and move funds immediately.
  4. Monitor implementation changes. Any Upgraded(address) event on high-value proxies should page humans and bots.
  5. Use emergency pause with separate keys. The emergency brake must not depend on the same compromised admin key.

Confidence notes

  • Firm: public reports agree the exploit was driven by compromised privileged authority and a malicious/unauthorized upgrade path.
  • Firm: public reports place the loss at about 18.4M UPC, roughly $70M.
  • Firm: withdrawByAdmin is named in multiple reports as the drain primitive.
  • Unclear: the off-chain method used to obtain the administrative key has not been publicly proven.
  • Representative: code shows the security shape of ProxyAdmin compromise, not verified UPCX source.

Sources

  • Halborn — Explained: The UPCX Hack (April 2025): https://www.halborn.com/blog/post/explained-the-upcx-hack-april-2025
  • SmartContractsHacking — UPCX Hack: https://smartcontractshacking.com/hacks/upcx-hack-2025
  • Incrypthos — UPCX Platform Suffers $70M Private Key Compromise and Contract Upgrade Exploit: https://incrypthos.com/security/upcx-platform-suffers-70-million-private-key-compromise-and-contract-upgrade-exploit/
  • Cyvers alert: https://x.com/CyversAlerts/status/1907046941906653633
  • UPCX acknowledgement: https://x.com/Upcxofficial/status/1907024397497749647