npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@1kpub/upgrade-control-contracts

v1.0.3

Published

Upgrade Control Contracts

Readme

Contract Upgrade Management System

This is a proxy-based smart contract upgrade management system that provides a secure and reliable contract upgrade mechanism, similar to a beacon proxy architecture for centrally managing multiple upgradeable contracts.

Core Features

🔧 Upgrade Manager (UpgradeManager)

  • Manages the registration and deregistration of upgradeable contracts
  • Supports contract implementation upgrades and rollbacks
  • Maintains version history and management
  • Provides access control and administrator transfer
  • Owner permission required for contract registration

🌍 Open Upgrade Manager (UpgradeManagerOpen)

  • Permissionless — anyone can register and manage their own upgradeable contracts
  • Uses namespace isolation to prevent tag conflicts between different users
  • Supports separation of registrant and administrator roles
  • Provides complete upgrade, rollback, and management functionality
  • Implements the IUpgradeManagerOpen interface

🔄 Upgrade Proxy (UpgradeProxy)

  • Based on OpenZeppelin's proxy pattern
  • Dynamically retrieves the latest logic contract address
  • Transparently delegates all function calls

📚 Upgrade Library (UpgradeLib)

  • Provides utility functions related to upgrade management
  • Centralized management of storage slots and constants
  • Simplifies the implementation of upgrade logic

🏗️ Upgrade Logic Base (UpgradeLogicBase)

  • Provides foundational functionality for upgradeable logic contracts
  • Integrates initializer and upgrade management capabilities
  • Abstract base contract for inheritance and extension

System Architecture

Centralized Management Mode (UpgradeManager)

User call → UpgradeProxy → Delegate call → Logic Contract (inherits UpgradeLogicBase)
                 ↓                            ↓
         UpgradeManager ← ← ← ← ← ← ← ← ← UpgradeLib (Utility Library)
           (Owner permission required)

Decentralized Management Mode (UpgradeManagerOpen)

User call → UpgradeProxy → Delegate call → Logic Contract (inherits UpgradeLogicBase)
                 ↓                            ↓
     UpgradeManagerOpen ← ← ← ← ← ← ← ← ← UpgradeLib (Utility Library)
        (Permissionless access)
              ↓
     Namespace isolation (registrant + tag)

Contract Components

1. IUpgradeManager.sol

Defines the interface for the upgrade manager, including:

  • ContractInfo struct: stores contract information (logic address, proxy address, administrator, version, activation status)
  • Event definitions: registration, upgrade, deregistration, admin transfer
  • Core function interfaces: create proxy, register, upgrade, rollback, etc.

2. UpgradeManager.sol

Core implementation of the upgrade manager:

  • Inherits Ownable2Step for ownership management
  • Implements the IUpgradeManager interface
  • Supports proxy deployment using CREATE2
  • Provides version management and historical tracking
  • Enforces access control (only Owner can register, only Admin can upgrade)

3. IUpgradeManagerOpen.sol

Interface definition for the open upgrade manager:

  • Extends IUpgradeManager with the namespacedTag parameter
  • Supports permissionless registration and management
  • Provides getNamespacedTag function for namespace computation
  • Clearly distinguishes between registration and management parameters

4. UpgradeManagerOpen.sol

Implementation of the permissionless upgrade manager:

  • Implements the IUpgradeManagerOpen interface
  • Anyone can register and manage their own upgradeable contracts
  • Uses keccak256(abi.encodePacked(registrant, tag)) for namespace isolation
  • Supports separation of registrant and administrator roles
  • Provides complete upgrade, rollback, and management functionality

5. UpgradeProxy.sol

Proxy contract implementation:

  • Inherits OpenZeppelin's Proxy contract
  • Uses UpgradeLib to manage storage slots
  • Dynamically fetches the current logic contract address
  • Transparently proxies all function calls

6. UpgradeLib.sol

Upgrade utility library:

  • Defines constants for upgrade-related storage slots
  • Provides functions to retrieve upgrade manager addresses
  • Provides functions to fetch upgrade tags, registration info, and admin addresses

7. UpgradeLogicBase.sol

Base class for upgradeable logic contracts:

  • Uses UpgradeLib to retrieve upgrade-related information
  • Provides internal functions to access the upgrade manager, tag, registration info, and admin
  • Abstract contract intended to be inherited by concrete logic contracts

Core Features

Version Management

  • Automatic version increments
  • Historical version tracking
  • Supports rollback to specified versions

Access Control

  • Centralized mode: Owner manages registration, Admin controls upgrades
  • Decentralized mode: Anyone can register, Admin controls upgrades
  • Supports admin role transfer
  • Only the administrator can perform upgrade operations

Security Mechanisms

  • Zero-address checks
  • Duplicate registration prevention
  • Logic contract address validation
  • Namespace isolation (in UpgradeManagerOpen)

Modular Design

  • Centralized upgrade logic managed via a utility library
  • Base class provides standardized upgrade functionality
  • Componentized architecture for scalability and maintainability
  • Dual-mode support: Centralized vs. Decentralized

Usage Examples

Centralized Mode (UpgradeManager)

Creating an Upgradeable Logic Contract

import { Initializable } from '@openzeppelin/contracts/proxy/utils/Initializable.sol';
import {
  UpgradeLogicBase
} from '@kyriework/upgrade-control-contracts/contracts/UpgradeLogicBase.sol';

contract MyContract is UpgradeLogicBase, Initializable {
  uint256 public value;

  constructor() {
    _disableInitializers();
  }

  function initialize(uint256 _value) public initializer {
    value = _value;
  }

  function setValue(uint256 _value) public {
    address admin = _upgradeAdminAddress();
    require(msg.sender == admin, 'Only admin can set value');
    value = _value;
  }

  function getUpgradeInfo() external view returns (address manager, bytes32 tag) {
    manager = _upgradeManagerAddress();
    tag = _upgradeTagBytes32();
  }
}

Deploying and Registering Contracts

UpgradeManager manager = new UpgradeManager(owner);

bytes32 tag = keccak256("MyContract");
address logic = address(new MyContract());
bytes memory initData = abi.encodeWithSignature("initialize(uint256)", 100);
(address proxy, bytes memory result) = manager.createProxy(tag, logic, admin, initData);

MyContract(proxy).setValue(200);

Decentralized Mode (UpgradeManagerOpen)

Deploying and Registering Contracts

UpgradeManagerOpen openManager = new UpgradeManagerOpen();

bytes32 tag = keccak256("MyContract");
address logic = address(new MyContract());
bytes memory initData = abi.encodeWithSignature("initialize(uint256)", 100);
(address proxy, bytes memory result) = openManager.createProxy(tag, logic, admin, initData);

bytes32 namespacedTag = openManager.getNamespacedTag(msg.sender, tag);

address newLogic = address(new MyContractV2());
openManager.upgrade(namespacedTag, newLogic); // Only admin can call

Access Control

address registrant = msg.sender;
address admin = 0x1234...;

openManager.createProxy(tag, logic, admin, initData);
bytes32 namespacedTag = openManager.getNamespacedTag(registrant, tag);
openManager.upgrade(namespacedTag, newLogic); // Must be called by admin

Upgrading a Contract

import { Initializable } from '@openzeppelin/contracts/proxy/utils/Initializable.sol';
import { UpgradeLogicBase } from '@kyriework/upgrade-control-contracts/contracts/UpgradeLogicBase.sol';

contract MyContractV2 is UpgradeLogicBase, Initializable {
    uint256 public value;
    uint256 public newFeature;

    constructor() {
        _disableInitializers();
    }

    function initialize(uint256 _value) public initializer {
        value = _value;
    }

    function setNewFeature(uint256 _newFeature) public {
        address admin = _upgradeAdminAddress();
        require(msg.sender == admin, "Only admin");
        newFeature = _newFeature;
    }
}

address newLogic = address(new MyContractV2());
manager.upgrade(tag, newLogic);

bytes32 namespacedTag = openManager.getNamespacedTag(registrant, tag);
openManager.upgrade(namespacedTag, newLogic);

Rolling Back a Contract

manager.rollback(tag, 1); // Roll back to version 1

openManager.rollback(namespacedTag, 1); // Roll back to version 1

Development & Testing

Install Dependencies

pnpm install

Compile Contracts

npx hardhat compile

Run Tests

npx hardhat test

Deploy Contracts

npx hardhat ignition deploy ./ignition/modules/UpgradeManager.js

Generate Test Reports

REPORT_GAS=true npx hardhat test

Tech Stack

  • Solidity ^0.8.20 — Smart contract programming language
  • OpenZeppelin — Secure smart contract library
  • Hardhat — Ethereum development environment
  • Proxy Pattern — Upgradeable contract architecture
  • Library Pattern — Code reuse and modularization
  • Namespace Isolation — Prevents conflicts in multi-user environments

Notes & Best Practices

  1. Storage Layout Compatibility: Ensure storage layout compatibility between versions.
  2. Access Control: Assign administrator roles carefully to avoid privilege misuse.
  3. Version Management: Thoroughly test before performing upgrades.
  4. Gas Optimization: Proxy calls incur additional gas overhead.
  5. Base Inheritance: Logic contracts should inherit UpgradeLogicBase to enable full upgrade functionality.
  6. Initializer Usage: Use the initializer modifier to ensure initialization functions are called only once.
  7. Namespace Management: In UpgradeManagerOpen, always use the correct namespacedTag for operations.
  8. Role Separation: Registrant and administrator roles can be distinct; allocate permissions appropriately.

Selection Guide

When to Use UpgradeManager

  • Centralized control and registration required
  • Enterprise-level applications with strict permission management
  • Fewer contracts and simpler management needs
  • Clear administrative authority structure

When to Use UpgradeManagerOpen

  • Open platforms allowing public contract registration
  • Decentralized applications minimizing centralized control
  • Multi-user environments requiring isolation
  • Flexible role management (Registrant ≠ Administrator)

License

MIT