Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make DockRegistry UUPS upgradeable #20

Merged
merged 4 commits into from
Aug 12, 2024
Merged
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
4 changes: 4 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ libs = ["lib"]
optimizer = true
optimizer_runs = 1000
gas_reports = ["ModuleKeeper", "DockRegistry", "Container"]
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]

[fmt]
bracket_spacing = true
Expand Down
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
@sablier/v2-core/=lib/v2-core/
@prb/math/=lib/prb-math/
@nomad-xyz/excessively-safe-call/=lib/nomad-xyz/excessively-safe-call/
Expand Down
25 changes: 24 additions & 1 deletion script/DeployDeterministicDockRegistry.s.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.26;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { Options } from "./../lib/openzeppelin-foundry-upgrades/src/Options.sol";
import { Core } from "./../lib/openzeppelin-foundry-upgrades/src/internal/Core.sol";

import { BaseScript } from "./Base.s.sol";
import { DockRegistry } from "./../src/DockRegistry.sol";
import { ModuleKeeper } from "./../src/ModuleKeeper.sol";
Expand All @@ -18,6 +22,25 @@ contract DeployDeterministicDockRegistry is BaseScript {
bytes32 salt = bytes32(abi.encodePacked(create2Salt));

// Deterministically deploy a {DockRegistry} contract
dockRegistry = new DockRegistry{ salt: salt }(initialOwner, moduleKeeper);
dockRegistry = DockRegistry(
deployDetermisticUUPSProxy(
salt, "DockRegistry.sol", abi.encodeCall(DockRegistry.initialize, (initialOwner, moduleKeeper))
)
);
}

/// @dev Deploys a UUPS proxy at deterministic addresses across chains based on a provided salt
/// @param salt Salt to use for deterministic deployment
/// @param contractName The name of the implementation contract
/// @param initializerData The ABI encoded call to be made to the initialize method
function deployDetermisticUUPSProxy(
bytes32 salt,
string memory contractName,
bytes memory initializerData
) internal returns (address) {
Options memory opts;
address impl = Core.deployImplementation(contractName, opts);

return address(new ERC1967Proxy{ salt: salt }(impl, initializerData));
}
}
36 changes: 29 additions & 7 deletions src/DockRegistry.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.26;

import { Ownable } from "./abstracts/Ownable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { IDockRegistry } from "./interfaces/IDockRegistry.sol";
import { Container } from "./Container.sol";
import { ModuleKeeper } from "./ModuleKeeper.sol";
import { Errors } from "./libraries/Errors.sol";

/// @title DockRegistry
/// @notice See the documentation in {IDockRegistry}
contract DockRegistry is IDockRegistry, Ownable {
contract DockRegistry is IDockRegistry, Initializable, OwnableUpgradeable, UUPSUpgradeable {
/// @dev Version identifier for the current implementation of the contract
string public constant VERSION = "1.0.0";

/*//////////////////////////////////////////////////////////////////////////
PUBLIC STORAGE
STORAGE
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IDockRegistry
Expand All @@ -26,23 +31,40 @@ contract DockRegistry is IDockRegistry, Ownable {
/// @inheritdoc IDockRegistry
mapping(address container => address owner) public override ownerOfContainer;

/// @dev Counter to keep track of the next dock ID
uint256 private _dockNextId;

/*//////////////////////////////////////////////////////////////////////////
PRIVATE STORAGE
RESERVED STORAGE
//////////////////////////////////////////////////////////////////////////*/

/// @dev Counter to keep track of the next dock ID
uint256 private _dockNextId;
/// @dev This empty reserved space is put in place to allow future versions to add new
/// variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[45] private __gap;

/*//////////////////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////////////////*/

/// @dev Lock the implementation contract
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

/// @dev Initializes the address of the {ModuleKeeper} contract, registry owner and sets the next dock ID to start from 1
constructor(address _initialOwner, ModuleKeeper _moduleKeeper) Ownable(_initialOwner) {
function initialize(address _initialOwner, ModuleKeeper _moduleKeeper) public initializer {
__Ownable_init(_initialOwner);
__UUPSUpgradeable_init();

_dockNextId = 1;
moduleKeeper = _moduleKeeper;
}

/// @dev Allows only the owner to upgrade the contract
function _authorizeUpgrade(address newImplementation) internal override onlyOwner { }

/*//////////////////////////////////////////////////////////////////////////
NON-CONSTANT FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
Expand Down
1 change: 0 additions & 1 deletion src/interfaces/IDockRegistry.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.26;

import { IContainer } from "./IContainer.sol";
import { Container } from "./../Container.sol";
import { IModuleKeeper } from "./IModuleKeeper.sol";
import { ModuleKeeper } from "./../ModuleKeeper.sol";
Expand Down
7 changes: 6 additions & 1 deletion test/Base.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { MockBadReceiver } from "./mocks/MockBadReceiver.sol";
import { Container } from "./../src/Container.sol";
import { ModuleKeeper } from "./../src/ModuleKeeper.sol";
import { DockRegistry } from "./../src/DockRegistry.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

abstract contract Base_Test is Test, Events {
/*//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -50,7 +51,11 @@ abstract contract Base_Test is Test, Events {

// Deploy test contracts
moduleKeeper = new ModuleKeeper({ _initialOwner: users.admin });
dockRegistry = new DockRegistry({ _initialOwner: users.admin, _moduleKeeper: moduleKeeper });

address implementation = address(new DockRegistry());
bytes memory data = abi.encodeWithSelector(DockRegistry.initialize.selector, users.admin, moduleKeeper);
dockRegistry = DockRegistry(address(new ERC1967Proxy(implementation, data)));

mockModule = new MockModule();
mockNonCompliantContainer = new MockNonCompliantContainer({ _owner: users.admin });
mockBadReceiver = new MockBadReceiver();
Expand Down