npm package: @kyriework/upgrade-control-contracts
Description: Upgrade Control Contracts
Author: Kyrie
Latest version: 1.1.3

(已经迁移至 kyriework-contracts 仓库)

# 合约升级管理系统

这是一个基于代理模式的智能合约升级管理系统，提供了安全可靠的合约升级机制，类似信标代理的集中管理多个可升级合约。

## 核心功能

### 🔧 升级管理器 (UpgradeManager)

- 管理可升级合约的注册与注销
- 支持合约实现的升级和回滚
- 版本历史记录和管理
- 权限控制和管理员转移
- **需要Owner权限**进行合约注册

### 🌍 开放升级管理器 (UpgradeManagerOpen)

- **无需许可**，任何人都可以注册和管理自己的可升级合约
- 使用**命名空间隔离**防止不同用户之间的tag冲突
- 支持注册人和管理员角色分离
- 提供完整的升级、回滚和管理功能
- 继承 `IUpgradeManagerOpen` 接口

### 🔄 升级代理 (UpgradeProxy)

- 基于OpenZeppelin的代理模式
- 动态获取最新的逻辑合约地址
- 透明的函数调用代理

### 📚 升级工具库 (UpgradeLib)

- 提供升级相关的实用工具函数
- 统一管理存储槽位和常量
- 简化升级逻辑的实现

### 🏗️ 升级逻辑基类 (UpgradeLogicBase)

- 为可升级逻辑合约提供基础功能
- 集成初始化器和升级管理功能
- 抽象基类，便于继承使用

## 系统架构

### 中心化管理模式 (UpgradeManager)

```
用户调用 → UpgradeProxy → 委托调用 → 逻辑合约 (继承 UpgradeLogicBase)
              ↓                            ↓
        UpgradeManager ← ← ← ← ← ← ← ← ← UpgradeLib (工具库)
          (需要Owner权限)
```

### 去中心化管理模式 (UpgradeManagerOpen)

```
用户调用 → UpgradeProxy → 委托调用 → 逻辑合约 (继承 UpgradeLogicBase)
              ↓                            ↓
    UpgradeManagerOpen ← ← ← ← ← ← ← ← ← UpgradeLib (工具库)
      (无需许可访问)
           ↓
    命名空间隔离 (registrant + tag)
```

## 合约组件

### 1. IUpgradeManager.sol

定义了升级管理器的接口，包含：

- `ContractInfo` 结构体：存储合约信息（逻辑地址、代理地址、管理员、版本、激活状态）
- 事件定义：注册、升级、注销、管理员转移
- 核心函数接口：创建代理、注册、升级、回滚等

### 2. UpgradeManager.sol

升级管理器的核心实现：

- 继承 `Ownable2Step` 提供所有权管理
- 实现 `IUpgradeManager` 接口
- 支持通过 CREATE2 部署代理合约
- 版本管理和历史记录
- 权限控制（只有Owner可以注册，只有管理员可以升级）

### 3. IUpgradeManagerOpen.sol

开放升级管理器的接口定义：

- 基于 `IUpgradeManager` 扩展，使用 `namespacedTag` 参数
- 支持无需许可的合约注册和管理
- 提供 `getNamespacedTag` 函数用于命名空间计算
- 明确区分注册函数和管理函数的参数类型

### 4. UpgradeManagerOpen.sol

无需许可的升级管理器实现：

- 实现 `IUpgradeManagerOpen` 接口
- **任何人都可以注册**和管理自己的可升级合约
- 使用 `keccak256(abi.encodePacked(registrant, tag))` 进行命名空间隔离
- 支持注册人和管理员角色分离
- 提供完整的升级、回滚和管理功能

### 5. UpgradeProxy.sol

代理合约实现：

- 继承 OpenZeppelin 的 `Proxy` 合约
- 使用 `UpgradeLib` 管理存储槽位
- 动态获取当前逻辑合约地址
- 透明代理所有函数调用

### 6. UpgradeLib.sol

升级工具库：

- 定义升级相关的存储槽位常量
- 提供获取升级管理器地址的函数
- 提供获取升级标签的函数
- 提供获取注册信息和管理员地址的函数

### 7. UpgradeLogicBase.sol

升级逻辑基类：

- 继承 OpenZeppelin 的 `Initializable` 合约
- 使用 `UpgradeLib` 获取升级相关信息
- 提供内部函数访问升级管理器、标签、注册信息和管理员
- 抽象合约，需要被具体逻辑合约继承

## 核心特性

### 版本管理

- 自动版本递增
- 历史版本记录
- 支持回滚到指定版本

### 权限控制

- **中心化模式**：Owner控制合约注册，管理员控制升级
- **去中心化模式**：任何人可以注册，管理员控制升级
- 支持管理员转移
- 只有管理员可以执行升级操作

### 安全机制

- 地址零值检查
- 重复注册防护
- 逻辑合约地址验证
- **命名空间隔离**（UpgradeManagerOpen）

### 模块化设计

- 工具库统一管理升级逻辑
- 基类提供标准升级功能
- 组件化架构，便于扩展和维护
- 双模式支持：中心化 vs 去中心化

## 使用示例

### 中心化模式 (UpgradeManager)

#### 创建可升级的逻辑合约

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

// 继承 UpgradeLogicBase 基类
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();
  }
}
```

#### 部署和注册合约

```solidity
// 1. 部署UpgradeManager
UpgradeManager manager = new UpgradeManager(owner);

// 2. 创建代理并注册合约
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);

// 3. 通过代理调用合约
MyContract(proxy).setValue(200);
```

### 去中心化模式 (UpgradeManagerOpen)

#### 部署和注册合约

```solidity
// 1. 部署UpgradeManagerOpen
UpgradeManagerOpen openManager = new UpgradeManagerOpen();

// 2. 任何人都可以创建代理并注册合约
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);

// 3. 获取命名空间标签
bytes32 namespacedTag = openManager.getNamespacedTag(msg.sender, tag);

// 4. 管理员可以升级合约
address newLogic = address(new MyContractV2());
openManager.upgrade(namespacedTag, newLogic); // 只有admin可以调用
```

#### 权限管理

```solidity
// 注册人和管理员可以是不同的地址
address registrant = msg.sender;      // 注册合约的用户
address admin = 0x1234...;           // 管理合约的管理员

// 创建代理时指定管理员
openManager.createProxy(tag, logic, admin, initData);

// 计算命名空间标签
bytes32 namespacedTag = openManager.getNamespacedTag(registrant, tag);

// 只有管理员可以升级
openManager.upgrade(namespacedTag, newLogic); // 必须由admin调用
```

### 升级合约

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

// 部署新的逻辑合约（继承 UpgradeLogicBase）
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);
```

### 回滚合约

```solidity
// 中心化模式回滚
manager.rollback(tag, 1); // 回滚到版本1

// 去中心化模式回滚
openManager.rollback(namespacedTag, 1); // 回滚到版本1
```

## 开发和测试

### 安装依赖

```shell
pnpm install
```

### 编译合约

```shell
npx hardhat compile
```

### 运行测试

```shell
npx hardhat test
```

### 部署合约

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

### 获取测试报告

```shell
REPORT_GAS=true npx hardhat test
```

## 技术栈

- **Solidity ^0.8.20**: 智能合约开发语言
- **OpenZeppelin**: 安全的智能合约库
- **Hardhat**: 以太坊开发环境
- **代理模式**: 可升级合约架构模式
- **库模式**: 代码复用和模块化
- **命名空间隔离**: 防止多用户环境下的冲突

## 注意事项

1. **存储布局兼容性**: 升级时需要保持存储布局的兼容性
2. **权限管理**: 合理设置管理员权限，避免权限滥用
3. **版本管理**: 建议在升级前进行充分测试
4. **Gas优化**: 代理调用会产生额外的Gas开销
5. **基类继承**: 逻辑合约应该继承 `UpgradeLogicBase` 以获得完整的升级功能
6. **初始化器**: 使用 `initializer` 修饰符确保初始化函数只被调用一次
7. **命名空间管理**: 在 `UpgradeManagerOpen` 中，确保使用正确的 `namespacedTag` 进行管理操作
8. **角色分离**: 注册人和管理员可以是不同的地址，合理规划权限分配

## 选择指南

### 使用 UpgradeManager 的场景

- 需要集中管理和控制合约注册
- 企业级应用，需要严格的权限控制
- 合约数量较少，管理相对简单
- 有明确的系统管理员角色

### 使用 UpgradeManagerOpen 的场景

- 开放平台，允许任何人注册可升级合约
- 去中心化应用，减少中心化控制
- 多用户环境，需要隔离不同用户的合约
- 需要灵活的权限管理（注册人 ≠ 管理员）

## 许可证

MIT