{"_id":"@1kpub/upgrade-control-contracts","_rev":"4-2c0849477befaa7462ef7448d1660278","name":"@1kpub/upgrade-control-contracts","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"@1kpub/upgrade-control-contracts","version":"1.0.0","keywords":["smart-contracts","upgradeable","proxy","ethereum","solidity","hardhat","upgrade-manager"],"author":{"name":"Kyrie"},"license":"MIT","_id":"@1kpub/upgrade-control-contracts@1.0.0","maintainers":[{"name":"kyrielam","email":"lamkencong@gmail.com"}],"dist":{"shasum":"da9fe64f65207bef7dd18537614441e39cbe2e1d","tarball":"https://registry.npmjs.org/@1kpub/upgrade-control-contracts/-/upgrade-control-contracts-1.0.0.tgz","fileCount":439,"integrity":"sha512-nN/aB5qfM4r7cUF648ZH64peAB1ZtJEnhT2XQv3j4er2naQM4xGlkudsFip31wkqxBj1TR0izT55LUF0sHjYRg==","signatures":[{"sig":"MEUCIQDaEvK9PuoBN3iS7taTHqOn/5hFT3CHYyQY/N+K8wqBBAIgFMJXOtFTMEis1vFXluNoaW8QndNnJDCkVOkdcxye5aA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3428697},"types":"typechain-types/index.ts","exports":{".":{"types":"./typechain-types/index.ts","default":"./typechain-types/index.ts"},"./abis/*":"./abis/*","./contracts/*":"./contracts/*","./typechain-types/*":"./typechain-types/*"},"gitHead":"964572bdcb18999c0569727ac623e5fdafec4c63","scripts":{"lint":"prettier --check .","test":"hardhat test","clean":"rm -rf abis typechain-types artifacts cache","compile":"hardhat compile","prepare":"husky install","release":"pnpm install && pnpm clean && pnpm compile && npm publish --access public","coverage":"hardhat coverage","lint:fix":"prettier --write ."},"_npmUser":{"name":"kyrielam","email":"lamkencong@gmail.com"},"_npmVersion":"11.4.2","description":"Upgrade Control Contracts","directories":{},"_nodeVersion":"24.3.0","dependencies":{"ethers":"^6.15.0","@openzeppelin/contracts":"^5.3.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.11.0","devDependencies":{"chai":"^4.5.0","husky":"^9.1.7","hardhat":"^2.25.0","ts-node":"^10.9.2","prettier":"^3.6.2","typechain":"^8.3.2","typescript":"^5.8.3","@types/chai":"^4.3.20","@types/node":"^24.0.10","lint-staged":"^16.1.2","@types/mocha":"^10.0.10","solidity-coverage":"^0.8.16","@typechain/hardhat":"^9.1.0","@typechain/ethers-v6":"^0.5.1","hardhat-abi-exporter":"^2.11.0","hardhat-gas-reporter":"^2.3.0","prettier-plugin-solidity":"^2.0.0","@nomicfoundation/hardhat-ethers":"^3.0.9","@nomicfoundation/hardhat-verify":"^2.0.14","@nomicfoundation/hardhat-toolbox":"^6.0.0","@nomicfoundation/hardhat-ignition":"^0.15.12","@nomicfoundation/hardhat-chai-matchers":"^2.0.9","@nomicfoundation/hardhat-ignition-ethers":"^0.15.13","@nomicfoundation/hardhat-network-helpers":"^1.0.13"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-control-contracts_1.0.0_1760070319770_0.3769771189999158","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@1kpub/upgrade-control-contracts","version":"1.0.1","keywords":["smart-contracts","upgradeable","proxy","ethereum","solidity","hardhat","upgrade-manager"],"author":{"name":"Kyrie"},"license":"MIT","_id":"@1kpub/upgrade-control-contracts@1.0.1","maintainers":[{"name":"kyrielam","email":"lamkencong@gmail.com"}],"dist":{"shasum":"260f3a4ad05923204567f66cfde18b7e39f92812","tarball":"https://registry.npmjs.org/@1kpub/upgrade-control-contracts/-/upgrade-control-contracts-1.0.1.tgz","fileCount":439,"integrity":"sha512-uJyUisEXZ9DA2FVXvJaEa4RKyYej23+6Yb0p0ixsELVW6mfJhwRxQR4kGvTIGe3foXtnbIMJfPafjj/jSEQutA==","signatures":[{"sig":"MEUCIHSG/kH90Nk3QcOgH/s91G6MPKz435bTAsataYiFziq9AiEAvbPb29+LRDXNnB2LErW1w+GUt2v85kxzETohuMhKgUQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3429950},"types":"typechain-types/index.ts","exports":{".":{"types":"./typechain-types/index.ts","default":"./typechain-types/index.ts"},"./abis/*":"./abis/*","./contracts/*":"./contracts/*","./typechain-types/*":"./typechain-types/*"},"gitHead":"76f3756d626f6ba94a34e7fab5d5562788faf5a2","scripts":{"lint":"prettier --check .","test":"hardhat test","clean":"rm -rf abis typechain-types artifacts cache","compile":"hardhat compile","prepare":"husky install","release":"pnpm install && pnpm clean && pnpm compile && npm publish --access public","coverage":"hardhat coverage","lint:fix":"prettier --write ."},"_npmUser":{"name":"kyrielam","email":"lamkencong@gmail.com"},"_npmVersion":"11.4.2","description":"Upgrade Control Contracts","directories":{},"_nodeVersion":"24.3.0","dependencies":{"ethers":"^6.15.0","@openzeppelin/contracts":"^5.3.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.11.0","devDependencies":{"chai":"^4.5.0","husky":"^9.1.7","hardhat":"^2.25.0","ts-node":"^10.9.2","prettier":"^3.6.2","typechain":"^8.3.2","typescript":"^5.8.3","@types/chai":"^4.3.20","@types/node":"^24.0.10","lint-staged":"^16.1.2","@types/mocha":"^10.0.10","solidity-coverage":"^0.8.16","@typechain/hardhat":"^9.1.0","@typechain/ethers-v6":"^0.5.1","hardhat-abi-exporter":"^2.11.0","hardhat-gas-reporter":"^2.3.0","prettier-plugin-solidity":"^2.0.0","@nomicfoundation/hardhat-ethers":"^3.0.9","@nomicfoundation/hardhat-verify":"^2.0.14","@nomicfoundation/hardhat-toolbox":"^6.0.0","@nomicfoundation/hardhat-ignition":"^0.15.12","@nomicfoundation/hardhat-chai-matchers":"^2.0.9","@nomicfoundation/hardhat-ignition-ethers":"^0.15.13","@nomicfoundation/hardhat-network-helpers":"^1.0.13"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-control-contracts_1.0.1_1762503635441_0.6251956518142119","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@1kpub/upgrade-control-contracts","version":"1.0.2","keywords":["smart-contracts","upgradeable","proxy","ethereum","solidity","hardhat","upgrade-manager"],"author":{"name":"Kyrie"},"license":"MIT","_id":"@1kpub/upgrade-control-contracts@1.0.2","maintainers":[{"name":"kyrielam","email":"lamkencong@gmail.com"}],"dist":{"shasum":"3a5f464a86b36abc96fe2fea9ca2219dc4a8e871","tarball":"https://registry.npmjs.org/@1kpub/upgrade-control-contracts/-/upgrade-control-contracts-1.0.2.tgz","fileCount":439,"integrity":"sha512-wYqHVmIisVakjxgIZn9ytyfs30kIRurXJKIgNjG9+ldUQ6bl5sCnGT3J/mYlwhDuT0T0CcWgCPEq3leAQ9yPZw==","signatures":[{"sig":"MEQCIBvoO62kp6ipMqLLqsMwUSjo2JlFLG2AD4zDDaBOy69qAiBsFIJfy253Ai+j7yvUkRGLABGGdljpUjMTqmfsHdvNVQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3429914},"types":"typechain-types/index.ts","exports":{".":{"types":"./typechain-types/index.ts","default":"./typechain-types/index.ts"},"./abis/*":"./abis/*","./contracts/*":"./contracts/*","./typechain-types/*":"./typechain-types/*"},"gitHead":"76f3756d626f6ba94a34e7fab5d5562788faf5a2","scripts":{"lint":"prettier --check .","test":"hardhat test","clean":"rm -rf abis typechain-types artifacts cache","compile":"hardhat compile","prepare":"husky install","release":"pnpm install && pnpm clean && pnpm compile && npm publish --access public","coverage":"hardhat coverage","lint:fix":"prettier --write ."},"_npmUser":{"name":"kyrielam","email":"lamkencong@gmail.com"},"_npmVersion":"11.4.2","description":"Upgrade Control Contracts","directories":{},"_nodeVersion":"24.3.0","dependencies":{"ethers":"^6.15.0","@openzeppelin/contracts":"^5.3.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.11.0","devDependencies":{"chai":"^4.5.0","husky":"^9.1.7","hardhat":"^2.25.0","ts-node":"^10.9.2","prettier":"^3.6.2","typechain":"^8.3.2","typescript":"^5.8.3","@types/chai":"^4.3.20","@types/node":"^24.0.10","lint-staged":"^16.1.2","@types/mocha":"^10.0.10","solidity-coverage":"^0.8.16","@typechain/hardhat":"^9.1.0","@typechain/ethers-v6":"^0.5.1","hardhat-abi-exporter":"^2.11.0","hardhat-gas-reporter":"^2.3.0","prettier-plugin-solidity":"^2.0.0","@nomicfoundation/hardhat-ethers":"^3.0.9","@nomicfoundation/hardhat-verify":"^2.0.14","@nomicfoundation/hardhat-toolbox":"^6.0.0","@nomicfoundation/hardhat-ignition":"^0.15.12","@nomicfoundation/hardhat-chai-matchers":"^2.0.9","@nomicfoundation/hardhat-ignition-ethers":"^0.15.13","@nomicfoundation/hardhat-network-helpers":"^1.0.13"},"_npmOperationalInternal":{"tmp":"tmp/upgrade-control-contracts_1.0.2_1762504080946_0.9094433629222405","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@1kpub/upgrade-control-contracts","version":"1.0.3","description":"Upgrade Control Contracts","types":"typechain-types/index.ts","exports":{".":{"types":"./typechain-types/index.ts","default":"./typechain-types/index.ts"},"./abis/*":"./abis/*","./contracts/*":"./contracts/*","./typechain-types/*":"./typechain-types/*"},"scripts":{"test":"hardhat test","compile":"hardhat compile","coverage":"hardhat coverage","prepare":"husky install","lint":"prettier --check .","lint:fix":"prettier --write .","clean":"rm -rf abis typechain-types artifacts cache","release":"pnpm install && pnpm clean && pnpm compile && npm publish --access public"},"keywords":["smart-contracts","upgradeable","proxy","ethereum","solidity","hardhat","upgrade-manager"],"author":{"name":"Kyrie"},"license":"MIT","packageManager":"pnpm@10.11.0","dependencies":{"@openzeppelin/contracts":"^5.3.0","ethers":"^6.15.0"},"devDependencies":{"@nomicfoundation/hardhat-chai-matchers":"^2.0.9","@nomicfoundation/hardhat-ethers":"^3.0.9","@nomicfoundation/hardhat-ignition":"^0.15.12","@nomicfoundation/hardhat-ignition-ethers":"^0.15.13","@nomicfoundation/hardhat-network-helpers":"^1.0.13","@nomicfoundation/hardhat-toolbox":"^6.0.0","@nomicfoundation/hardhat-verify":"^2.0.14","@typechain/ethers-v6":"^0.5.1","@typechain/hardhat":"^9.1.0","@types/chai":"^4.3.20","@types/mocha":"^10.0.10","@types/node":"^24.0.10","chai":"^4.5.0","hardhat":"^2.25.0","hardhat-abi-exporter":"^2.11.0","hardhat-gas-reporter":"^2.3.0","husky":"^9.1.7","lint-staged":"^16.1.2","prettier":"^3.6.2","prettier-plugin-solidity":"^2.0.0","solidity-coverage":"^0.8.16","ts-node":"^10.9.2","typechain":"^8.3.2","typescript":"^5.8.3"},"_id":"@1kpub/upgrade-control-contracts@1.0.3","gitHead":"e50145224b06c6df49247af6b55a7dae878f8c81","_nodeVersion":"24.3.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-N9DLrjkIEtc8MiG1nRrmWksHBrVPES+oOBvom/nNUoa4CZzPs+NeaBes5y8prjXH6r4LcG5mIAYgBfmKlo5J1A==","shasum":"3dde5fc1ed0a9f8a538136bdc48981d3d2401dae","tarball":"https://registry.npmjs.org/@1kpub/upgrade-control-contracts/-/upgrade-control-contracts-1.0.3.tgz","fileCount":439,"unpackedSize":3429729,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDIRsbFN50r9qnYhmts2+o8uHYG9qnGF4MlO5C3zZtHLgIgOWs++HRduq/QuKxNRBNRmJPD8x402jnZlgdjqvbH4lA="}]},"_npmUser":{"name":"kyrielam","email":"lamkencong@gmail.com"},"directories":{},"maintainers":[{"name":"kyrielam","email":"lamkencong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/upgrade-control-contracts_1.0.3_1765177617912_0.24471457709108058"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-10T04:25:19.650Z","modified":"2025-12-08T07:06:58.407Z","1.0.0":"2025-10-10T04:25:20.271Z","1.0.1":"2025-11-07T08:20:35.690Z","1.0.2":"2025-11-07T08:28:01.180Z","1.0.3":"2025-12-08T07:06:58.171Z"},"author":{"name":"Kyrie"},"license":"MIT","keywords":["smart-contracts","upgradeable","proxy","ethereum","solidity","hardhat","upgrade-manager"],"description":"Upgrade Control Contracts","maintainers":[{"name":"kyrielam","email":"lamkencong@gmail.com"}],"readme":"# Contract Upgrade Management System\n\nThis 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.\n\n## Core Features\n\n### 🔧 Upgrade Manager (`UpgradeManager`)\n\n- Manages the registration and deregistration of upgradeable contracts\n- Supports contract implementation upgrades and rollbacks\n- Maintains version history and management\n- Provides access control and administrator transfer\n- **Owner permission required** for contract registration\n\n### 🌍 Open Upgrade Manager (`UpgradeManagerOpen`)\n\n- **Permissionless** — anyone can register and manage their own upgradeable contracts\n- Uses **namespace isolation** to prevent tag conflicts between different users\n- Supports separation of registrant and administrator roles\n- Provides complete upgrade, rollback, and management functionality\n- Implements the `IUpgradeManagerOpen` interface\n\n### 🔄 Upgrade Proxy (`UpgradeProxy`)\n\n- Based on OpenZeppelin's proxy pattern\n- Dynamically retrieves the latest logic contract address\n- Transparently delegates all function calls\n\n### 📚 Upgrade Library (`UpgradeLib`)\n\n- Provides utility functions related to upgrade management\n- Centralized management of storage slots and constants\n- Simplifies the implementation of upgrade logic\n\n### 🏗️ Upgrade Logic Base (`UpgradeLogicBase`)\n\n- Provides foundational functionality for upgradeable logic contracts\n- Integrates initializer and upgrade management capabilities\n- Abstract base contract for inheritance and extension\n\n## System Architecture\n\n### Centralized Management Mode (`UpgradeManager`)\n\n```\nUser call → UpgradeProxy → Delegate call → Logic Contract (inherits UpgradeLogicBase)\n                 ↓                            ↓\n         UpgradeManager ← ← ← ← ← ← ← ← ← UpgradeLib (Utility Library)\n           (Owner permission required)\n```\n\n### Decentralized Management Mode (`UpgradeManagerOpen`)\n\n```\nUser call → UpgradeProxy → Delegate call → Logic Contract (inherits UpgradeLogicBase)\n                 ↓                            ↓\n     UpgradeManagerOpen ← ← ← ← ← ← ← ← ← UpgradeLib (Utility Library)\n        (Permissionless access)\n              ↓\n     Namespace isolation (registrant + tag)\n```\n\n## Contract Components\n\n### 1. `IUpgradeManager.sol`\n\nDefines the interface for the upgrade manager, including:\n\n- `ContractInfo` struct: stores contract information (logic address, proxy address, administrator, version, activation status)\n- Event definitions: registration, upgrade, deregistration, admin transfer\n- Core function interfaces: create proxy, register, upgrade, rollback, etc.\n\n### 2. `UpgradeManager.sol`\n\nCore implementation of the upgrade manager:\n\n- Inherits `Ownable2Step` for ownership management\n- Implements the `IUpgradeManager` interface\n- Supports proxy deployment using CREATE2\n- Provides version management and historical tracking\n- Enforces access control (only Owner can register, only Admin can upgrade)\n\n### 3. `IUpgradeManagerOpen.sol`\n\nInterface definition for the open upgrade manager:\n\n- Extends `IUpgradeManager` with the `namespacedTag` parameter\n- Supports permissionless registration and management\n- Provides `getNamespacedTag` function for namespace computation\n- Clearly distinguishes between registration and management parameters\n\n### 4. `UpgradeManagerOpen.sol`\n\nImplementation of the permissionless upgrade manager:\n\n- Implements the `IUpgradeManagerOpen` interface\n- **Anyone can register** and manage their own upgradeable contracts\n- Uses `keccak256(abi.encodePacked(registrant, tag))` for namespace isolation\n- Supports separation of registrant and administrator roles\n- Provides complete upgrade, rollback, and management functionality\n\n### 5. `UpgradeProxy.sol`\n\nProxy contract implementation:\n\n- Inherits OpenZeppelin's `Proxy` contract\n- Uses `UpgradeLib` to manage storage slots\n- Dynamically fetches the current logic contract address\n- Transparently proxies all function calls\n\n### 6. `UpgradeLib.sol`\n\nUpgrade utility library:\n\n- Defines constants for upgrade-related storage slots\n- Provides functions to retrieve upgrade manager addresses\n- Provides functions to fetch upgrade tags, registration info, and admin addresses\n\n### 7. `UpgradeLogicBase.sol`\n\nBase class for upgradeable logic contracts:\n\n- Uses `UpgradeLib` to retrieve upgrade-related information\n- Provides internal functions to access the upgrade manager, tag, registration info, and admin\n- Abstract contract intended to be inherited by concrete logic contracts\n\n## Core Features\n\n### Version Management\n\n- Automatic version increments\n- Historical version tracking\n- Supports rollback to specified versions\n\n### Access Control\n\n- **Centralized mode**: Owner manages registration, Admin controls upgrades\n- **Decentralized mode**: Anyone can register, Admin controls upgrades\n- Supports admin role transfer\n- Only the administrator can perform upgrade operations\n\n### Security Mechanisms\n\n- Zero-address checks\n- Duplicate registration prevention\n- Logic contract address validation\n- **Namespace isolation** (in `UpgradeManagerOpen`)\n\n### Modular Design\n\n- Centralized upgrade logic managed via a utility library\n- Base class provides standardized upgrade functionality\n- Componentized architecture for scalability and maintainability\n- Dual-mode support: Centralized vs. Decentralized\n\n## Usage Examples\n\n### Centralized Mode (`UpgradeManager`)\n\n#### Creating an Upgradeable Logic Contract\n\n```solidity\nimport { Initializable } from '@openzeppelin/contracts/proxy/utils/Initializable.sol';\nimport {\n  UpgradeLogicBase\n} from '@kyriework/upgrade-control-contracts/contracts/UpgradeLogicBase.sol';\n\ncontract MyContract is UpgradeLogicBase, Initializable {\n  uint256 public value;\n\n  constructor() {\n    _disableInitializers();\n  }\n\n  function initialize(uint256 _value) public initializer {\n    value = _value;\n  }\n\n  function setValue(uint256 _value) public {\n    address admin = _upgradeAdminAddress();\n    require(msg.sender == admin, 'Only admin can set value');\n    value = _value;\n  }\n\n  function getUpgradeInfo() external view returns (address manager, bytes32 tag) {\n    manager = _upgradeManagerAddress();\n    tag = _upgradeTagBytes32();\n  }\n}\n```\n\n#### Deploying and Registering Contracts\n\n```solidity\nUpgradeManager manager = new UpgradeManager(owner);\n\nbytes32 tag = keccak256(\"MyContract\");\naddress logic = address(new MyContract());\nbytes memory initData = abi.encodeWithSignature(\"initialize(uint256)\", 100);\n(address proxy, bytes memory result) = manager.createProxy(tag, logic, admin, initData);\n\nMyContract(proxy).setValue(200);\n```\n\n### Decentralized Mode (`UpgradeManagerOpen`)\n\n#### Deploying and Registering Contracts\n\n```solidity\nUpgradeManagerOpen openManager = new UpgradeManagerOpen();\n\nbytes32 tag = keccak256(\"MyContract\");\naddress logic = address(new MyContract());\nbytes memory initData = abi.encodeWithSignature(\"initialize(uint256)\", 100);\n(address proxy, bytes memory result) = openManager.createProxy(tag, logic, admin, initData);\n\nbytes32 namespacedTag = openManager.getNamespacedTag(msg.sender, tag);\n\naddress newLogic = address(new MyContractV2());\nopenManager.upgrade(namespacedTag, newLogic); // Only admin can call\n```\n\n#### Access Control\n\n```solidity\naddress registrant = msg.sender;\naddress admin = 0x1234...;\n\nopenManager.createProxy(tag, logic, admin, initData);\nbytes32 namespacedTag = openManager.getNamespacedTag(registrant, tag);\nopenManager.upgrade(namespacedTag, newLogic); // Must be called by admin\n```\n\n### Upgrading a Contract\n\n```solidity\nimport { Initializable } from '@openzeppelin/contracts/proxy/utils/Initializable.sol';\nimport { UpgradeLogicBase } from '@kyriework/upgrade-control-contracts/contracts/UpgradeLogicBase.sol';\n\ncontract MyContractV2 is UpgradeLogicBase, Initializable {\n    uint256 public value;\n    uint256 public newFeature;\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(uint256 _value) public initializer {\n        value = _value;\n    }\n\n    function setNewFeature(uint256 _newFeature) public {\n        address admin = _upgradeAdminAddress();\n        require(msg.sender == admin, \"Only admin\");\n        newFeature = _newFeature;\n    }\n}\n\naddress newLogic = address(new MyContractV2());\nmanager.upgrade(tag, newLogic);\n\nbytes32 namespacedTag = openManager.getNamespacedTag(registrant, tag);\nopenManager.upgrade(namespacedTag, newLogic);\n```\n\n### Rolling Back a Contract\n\n```solidity\nmanager.rollback(tag, 1); // Roll back to version 1\n\nopenManager.rollback(namespacedTag, 1); // Roll back to version 1\n```\n\n## Development & Testing\n\n### Install Dependencies\n\n```shell\npnpm install\n```\n\n### Compile Contracts\n\n```shell\nnpx hardhat compile\n```\n\n### Run Tests\n\n```shell\nnpx hardhat test\n```\n\n### Deploy Contracts\n\n```shell\nnpx hardhat ignition deploy ./ignition/modules/UpgradeManager.js\n```\n\n### Generate Test Reports\n\n```shell\nREPORT_GAS=true npx hardhat test\n```\n\n## Tech Stack\n\n- **Solidity ^0.8.20** — Smart contract programming language\n- **OpenZeppelin** — Secure smart contract library\n- **Hardhat** — Ethereum development environment\n- **Proxy Pattern** — Upgradeable contract architecture\n- **Library Pattern** — Code reuse and modularization\n- **Namespace Isolation** — Prevents conflicts in multi-user environments\n\n## Notes & Best Practices\n\n1. **Storage Layout Compatibility**: Ensure storage layout compatibility between versions.\n2. **Access Control**: Assign administrator roles carefully to avoid privilege misuse.\n3. **Version Management**: Thoroughly test before performing upgrades.\n4. **Gas Optimization**: Proxy calls incur additional gas overhead.\n5. **Base Inheritance**: Logic contracts should inherit `UpgradeLogicBase` to enable full upgrade functionality.\n6. **Initializer Usage**: Use the `initializer` modifier to ensure initialization functions are called only once.\n7. **Namespace Management**: In `UpgradeManagerOpen`, always use the correct `namespacedTag` for operations.\n8. **Role Separation**: Registrant and administrator roles can be distinct; allocate permissions appropriately.\n\n## Selection Guide\n\n### When to Use `UpgradeManager`\n\n- Centralized control and registration required\n- Enterprise-level applications with strict permission management\n- Fewer contracts and simpler management needs\n- Clear administrative authority structure\n\n### When to Use `UpgradeManagerOpen`\n\n- Open platforms allowing public contract registration\n- Decentralized applications minimizing centralized control\n- Multi-user environments requiring isolation\n- Flexible role management (Registrant ≠ Administrator)\n\n## License\n\nMIT\n","readmeFilename":"README.md"}