From 7a8330119a5072236e295bf320fd374777e12bbf Mon Sep 17 00:00:00 2001 From: Jem <0x0xjem@gmail.com> Date: Wed, 5 Mar 2025 23:03:56 +0400 Subject: [PATCH 1/2] Modify installModule to allow for version skipping --- src/modules/Modules.sol | 9 ++--- test/modules/Modules/installModule.t.sol | 44 +++++++++++++++++------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/modules/Modules.sol b/src/modules/Modules.sol index 0914d0f0..a3cfb8d9 100644 --- a/src/modules/Modules.sol +++ b/src/modules/Modules.sol @@ -63,7 +63,7 @@ abstract contract WithModules is Owned { /// @dev - The module is not a contract /// @dev - The module has an invalid Veecode /// @dev - The module (or other versions) is already installed - /// @dev - The module version is not one greater than the latest version + /// @dev - The module version is not greater than the latest version /// /// @param newModule_ The new module function installModule( @@ -75,9 +75,10 @@ abstract contract WithModules is Owned { ensureValidVeecode(veecode); (Keycode keycode, uint8 version) = unwrapVeecode(veecode); - // Validate that the module version is one greater than the latest version + // Validate that the module version is greater than the latest version ModStatus storage status = getModuleStatus[keycode]; - if (version != status.latestVersion + 1) revert InvalidModuleInstall(keycode, version); + uint8 currentVersion = status.latestVersion; + if (version <= currentVersion) revert InvalidModuleInstall(keycode, version); // Store module data and remove sunset if applied status.latestVersion = version; @@ -85,7 +86,7 @@ abstract contract WithModules is Owned { getModuleForVeecode[veecode] = newModule_; // If the module is not already installed, add it to the list of modules - if (version == uint8(1)) { + if (currentVersion == uint8(0)) { modules.push(keycode); modulesCount++; } diff --git a/test/modules/Modules/installModule.t.sol b/test/modules/Modules/installModule.t.sol index bd91e3d7..c3615e34 100644 --- a/test/modules/Modules/installModule.t.sol +++ b/test/modules/Modules/installModule.t.sol @@ -78,26 +78,44 @@ contract InstallModuleTest is Test { _withModules.installModule(moduleZero); } - function testReverts_whenInitialVersionIncorrect() external { - Module upgradedModule = new MockModuleV2(address(_withModules)); - - bytes memory err = - abi.encodeWithSelector(WithModules.InvalidModuleInstall.selector, toKeycode("MOCK"), 2); - vm.expectRevert(err); + function test_whenInitialVersionSkips() external { + Module initialModule = new MockModuleV2(address(_withModules)); // Install version 2 (skips version 1) - _withModules.installModule(upgradedModule); + _withModules.installModule(initialModule); + + // Check that the module is installed + Module module = _withModules.getModuleForVeecode(initialModule.VEECODE()); + assertEq(address(module), address(initialModule)); + + // Check that the latest version is recorded + (uint8 moduleLatestVersion,) = _withModules.getModuleStatus(toKeycode("MOCK")); + assertEq(moduleLatestVersion, 2); + + // Check that the modules array is updated + uint256 modulesCount = _withModules.modulesCount(); + assertEq(modulesCount, 1); + assertEq(fromKeycode(_withModules.modules(0)), "MOCK"); } - function testReverts_whenNewerVersionSkips() external whenVersion1IsInstalled { + function test_whenNewerVersionSkips() external whenVersion1IsInstalled { Module upgradedModule = new MockModuleV3(address(_withModules)); - bytes memory err = - abi.encodeWithSelector(WithModules.InvalidModuleInstall.selector, toKeycode("MOCK"), 3); - vm.expectRevert(err); - - // Install version 3 + // Upgrade from version 1 to version 3 (skips version 2) _withModules.installModule(upgradedModule); + + // Check that the module is installed + Module module = _withModules.getModuleForVeecode(upgradedModule.VEECODE()); + assertEq(address(module), address(upgradedModule)); + + // Check that the latest version is recorded + (uint8 moduleLatestVersion,) = _withModules.getModuleStatus(toKeycode("MOCK")); + assertEq(moduleLatestVersion, 3); + + // Check that the modules array is updated + uint256 modulesCount = _withModules.modulesCount(); + assertEq(modulesCount, 1); + assertEq(fromKeycode(_withModules.modules(0)), "MOCK"); } function testReverts_invalidVeecode() external { From 8476982e970c1fa50927204748d07095b835d4d1 Mon Sep 17 00:00:00 2001 From: Jem <0x0xjem@gmail.com> Date: Wed, 5 Mar 2025 23:11:43 +0400 Subject: [PATCH 2/2] Add VERSION() function to AuctionHouse --- src/AtomicAuctionHouse.sol | 7 +++++++ src/BatchAuctionHouse.sol | 7 +++++++ src/interfaces/IAuctionHouse.sol | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/src/AtomicAuctionHouse.sol b/src/AtomicAuctionHouse.sol index 797b3c72..67ede642 100644 --- a/src/AtomicAuctionHouse.sol +++ b/src/AtomicAuctionHouse.sol @@ -46,6 +46,13 @@ contract AtomicAuctionHouse is IAtomicAuctionHouse, AuctionHouse { address permit2_ ) AuctionHouse(owner_, protocol_, permit2_) {} + // ========== VERSIONING ========== // + + /// @inheritdoc IAuctionHouse + function VERSION() external pure returns (uint8 major, uint8 minor) { + return (1, 1); + } + // ========== AUCTION MANAGEMENT ========== // /// @inheritdoc AuctionHouse diff --git a/src/BatchAuctionHouse.sol b/src/BatchAuctionHouse.sol index a7f44631..e5b22fa3 100644 --- a/src/BatchAuctionHouse.sol +++ b/src/BatchAuctionHouse.sol @@ -53,6 +53,13 @@ contract BatchAuctionHouse is IBatchAuctionHouse, AuctionHouse { address permit2_ ) AuctionHouse(owner_, protocol_, permit2_) {} + // ========== VERSIONING ========== // + + /// @inheritdoc IAuctionHouse + function VERSION() external pure returns (uint8 major, uint8 minor) { + return (1, 1); + } + // ========== AUCTION MANAGEMENT ========== // /// @inheritdoc AuctionHouse diff --git a/src/interfaces/IAuctionHouse.sol b/src/interfaces/IAuctionHouse.sol index 458cbda8..a4d7fd35 100644 --- a/src/interfaces/IAuctionHouse.sol +++ b/src/interfaces/IAuctionHouse.sol @@ -115,6 +115,11 @@ interface IAuctionHouse { uint48 referrerFee; // 6 bytes } + // ========== VERSIONING ========== // + + /// @notice The version of the AuctionHouse + function VERSION() external view returns (uint8 major, uint8 minor); + // ========== AUCTION MANAGEMENT ========== // /// @notice Creates a new auction lot