Skip to content

Commit

Permalink
Demo of struct based semver
Browse files Browse the repository at this point in the history
  • Loading branch information
maurelian committed Jan 14, 2025
1 parent 6c44b0b commit 468edad
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
10 changes: 6 additions & 4 deletions packages/contracts-bedrock/src/L1/ProtocolVersions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/O
import { Storage } from "src/libraries/Storage.sol";

// Interfaces
import { ISemver } from "interfaces/universal/ISemver.sol";
import { Semver } from "src/universal/Semver.sol";

/// @notice ProtocolVersion is a numeric identifier of the protocol version.
type ProtocolVersion is uint256;

/// @custom:proxied true
/// @title ProtocolVersions
/// @notice The ProtocolVersions contract is used to manage superchain protocol version information.
contract ProtocolVersions is OwnableUpgradeable, ISemver {
contract ProtocolVersions is OwnableUpgradeable, Semver {
/// @notice Enum representing different types of updates.
/// @custom:value REQUIRED_PROTOCOL_VERSION Represents an update to the required protocol version.
/// @custom:value RECOMMENDED_PROTOCOL_VERSION Represents an update to the recommended protocol version.
Expand All @@ -41,8 +41,10 @@ contract ProtocolVersions is OwnableUpgradeable, ISemver {
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);

/// @notice Semantic version.
/// @custom:semver 1.0.1-beta.6
string public constant version = "1.0.1-beta.6";
/// @custom:semver 1.0.2
function _version() internal pure override returns (Versions memory) {
return Versions(1, 0, 2);
}

/// @notice Constructs the ProtocolVersion contract.
constructor() {
Expand Down
39 changes: 39 additions & 0 deletions packages/contracts-bedrock/src/universal/Semver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { LibString } from "@solady/utils/LibString.sol";

/// @title Semver
/// @notice Semver is a simple contract for ensuring that contracts are
/// versioned using semantic versioning.
abstract contract Semver {
/// @notice Spacing constant for version components. Used to convert the MAJOR, MINOR, and PATCH components to a
/// uint64.
uint64 private constant SPACING = 1_000_000;

struct Versions {
uint16 major;
uint16 minor;
uint16 patch;
}

/// @notice Getter for the semantic version of the contract. This must be implemented on each contract.
function _version() internal pure virtual returns (Versions memory);

/// @notice Getter for the semantic version of the contract. This is not
/// meant to be used onchain but instead meant to be used by offchain
/// tooling.
/// @return Semver contract version as a string.
function version() external view returns (string memory) {
Versions memory v = _version();
return string.concat(
LibString.toString(v.major), ".", LibString.toString(v.minor), ".", LibString.toString(v.patch)
);
}

/// @notice Converts a contact's semver to a uint64 with padding for use with the reinitializer modifier.
function reinitializerValue() public pure returns (uint64) {
Versions memory v = _version();
return (v.major * SPACING ** 2) + (v.minor * SPACING) + v.patch;
}
}
34 changes: 34 additions & 0 deletions packages/contracts-bedrock/test/universal/Semver.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { Test } from "forge-std/Test.sol";
import { Semver } from "src/universal/Semver.sol";

/// @notice A mock contract that implements Semver
contract MockSemver is Semver {
function _version() internal pure override returns (Semver.Versions memory) {
return Semver.Versions(1, 2, 3);
}
}

/// @title SemverTest
/// @notice Tests for the Semver interface
contract SemverTest is Test {
/// @notice The mock Semver contract
MockSemver semver;

/// @notice Deploy the mock contract
function setUp() public {
semver = new MockSemver();
}

/// @notice Test that the version is returned correctly
function test_version() public {
assertEq(semver.version(), "1.2.3");
}

/// @notice Test that the reinitializerValue function returns the correct uint64
function test_reinitializerValue() public {
assertEq(uint256(semver.reinitializerValue()), 1000002000003);
}
}

0 comments on commit 468edad

Please sign in to comment.