Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/AtomicAuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/BatchAuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/IAuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions src/modules/Modules.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -75,17 +75,18 @@ 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;
if (status.sunset) status.sunset = false;
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++;
}
Expand Down
44 changes: 31 additions & 13 deletions test/modules/Modules/installModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading