@@ -33,6 +33,7 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
3333 address _poRepMarket;
3434 address _SPRegistry;
3535 address _beacon;
36+ address _admin;
3637 }
3738
3839 // keccak256(abi.encode(uint256(keccak256("porepmarket.storage.ValidatorFactoryStorage")) - 1)) & ~bytes32(uint256(0xff))
@@ -59,13 +60,15 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
5960 error InstanceAlreadyExists ();
6061 error InvalidAdminAddress ();
6162 error InvalidClientAddress ();
62- error InvalidSlcAddress ();
6363 error InvalidPoRepMarketAddress ();
6464 error InvalidClientSmartContractAddress ();
6565 error InvalidFilecoinPayAddress ();
6666 error InvalidPoRepServiceAddress ();
6767 error InvalidSliScorerAddress ();
6868 error InvalidSPRegistryAddress ();
69+ error InvalidImplementationAddress ();
70+ error InvalidNewAdminAddress ();
71+ error RoleManagementDisabled ();
6972
7073 /**
7174 * @notice Emitted when a new proxy is successfully created
@@ -74,19 +77,33 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
7477 */
7578 event ProxyCreated (address indexed proxy , uint256 indexed dealId );
7679
80+ /**
81+ * @notice Emitted when the admin is changed
82+ * @param newAdmin The address of the new admin
83+ */
84+ event AdminChanged (address indexed newAdmin );
85+
7786 /**
7887 * @notice Initializes the contract
7988 * @dev Initializes the contract by setting a default admin role and a UUPS upgradeable role
8089 * @param admin The address of the admin responsible for the contract
8190 * @param implementation The address of the implementation contract
8291 */
8392 function initialize (address admin , address implementation ) public initializer {
93+ if (admin == address (0 )) {
94+ revert InvalidAdminAddress ();
95+ }
96+ if (implementation == address (0 )) {
97+ revert InvalidImplementationAddress ();
98+ }
99+
84100 __AccessControl_init ();
85101 _grantRole (DEFAULT_ADMIN_ROLE, admin);
86102 _grantRole (UPGRADER_ROLE, admin);
87103
88104 ValidatorFactoryStorage storage $ = s ();
89105 $._beacon = address (new UpgradeableBeacon (implementation, admin));
106+ $._admin = admin;
90107 }
91108
92109 /**
@@ -127,12 +144,9 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
127144 * @notice Creates a new instance of an upgradeable contract.
128145 * @dev Uses BeaconProxy to create a new proxy instance, pointing to the Beacon for the logic contract.
129146 * @dev Reverts if an instance for the given dealId already exists.
130- * @param admin The address of the admin responsible for the contract.
131147 * @param dealId The dealId for which the proxy was created.
132148 */
133- function create (address admin , uint256 dealId ) external {
134- if (admin == address (0 )) revert InvalidAdminAddress ();
135-
149+ function create (uint256 dealId ) external {
136150 ValidatorFactoryStorage storage $ = s ();
137151 if ($._instances[dealId] != address (0 )) revert InstanceAlreadyExists ();
138152
@@ -146,7 +160,7 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
146160 abi.encodeCall (
147161 Validator.initialize,
148162 (
149- admin ,
163+ $._admin ,
150164 $._poRepService,
151165 $._filecoinPay,
152166 $._sliScorer,
@@ -159,7 +173,7 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
159173 )
160174 );
161175 // forge-lint: disable-next-line(asm-keccak256)
162- bytes32 salt = keccak256 (abi.encode (admin , dealId));
176+ bytes32 salt = keccak256 (abi.encode ($._admin , dealId));
163177 address proxy = Create2.computeAddress (salt, keccak256 (initCode), address (this ));
164178 $._instances[dealId] = proxy;
165179 $._isValidatorContract[proxy] = true ;
@@ -168,6 +182,51 @@ contract ValidatorFactory is UUPSUpgradeable, AccessControlUpgradeable {
168182 emit ProxyCreated (proxy, dealId);
169183 }
170184
185+ /**
186+ * @notice Sets a new admin for the contract and revoke the role from the old admin
187+ * @dev Only callable by the current admin. Reverts if the new admin address is the zero address.
188+ * @param newAdmin The new admin address
189+ */
190+ function setAdmin (address newAdmin ) external onlyRole (DEFAULT_ADMIN_ROLE) {
191+ if (newAdmin == address (0 )) {
192+ revert InvalidNewAdminAddress ();
193+ }
194+ ValidatorFactoryStorage storage $ = s ();
195+
196+ _revokeRole (DEFAULT_ADMIN_ROLE, $._admin);
197+ _grantRole (DEFAULT_ADMIN_ROLE, newAdmin);
198+ $._admin = newAdmin;
199+
200+ emit AdminChanged (newAdmin);
201+ }
202+
203+ // solhint-disable use-natspec
204+ /**
205+ * @notice Disabled role management functions
206+ * @dev This contract has a fixed admin and does not allow for dynamic role management
207+ */
208+ function grantRole (bytes32 , address ) public pure override {
209+ revert RoleManagementDisabled ();
210+ }
211+
212+ /**
213+ * @notice Disabled role management functions
214+ * @dev This contract has a fixed admin and does not allow for dynamic role management
215+ */
216+ function revokeRole (bytes32 , address ) public pure override {
217+ revert RoleManagementDisabled ();
218+ }
219+
220+ /**
221+ * @notice Disabled role management functions
222+ * @dev This contract has a fixed admin and does not allow for dynamic role management
223+ */
224+ function renounceRole (bytes32 , address ) public pure override {
225+ revert RoleManagementDisabled ();
226+ }
227+
228+ // solhint-enable use-natspec
229+
171230 /**
172231 * @notice Checks if an address is a validator contract
173232 * @param contractAddress The address to check
0 commit comments