Skip to content

Commit

Permalink
Merge pull request #20 from metadock/feat/upgradeable-dock-registry
Browse files Browse the repository at this point in the history
Make `DockRegistry` UUPS upgradeable
  • Loading branch information
gabrielstoica authored Aug 12, 2024
2 parents 625b11a + bccb1e0 commit 4a13637
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 10 deletions.
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

0 comments on commit 4a13637

Please sign in to comment.