Skip to content

Commit d53f3dd

Browse files
authored
Merge pull request #77 from PracticalParticle/work
Work
2 parents 605c5b8 + 2d067c5 commit d53f3dd

24 files changed

Lines changed: 308 additions & 188 deletions

File tree

contracts/core/access/RuntimeRBAC.sol

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,8 @@ abstract contract RuntimeRBAC is BaseStateMachine, IRuntimeRBAC {
4444
uint256 timeLockPeriodSec,
4545
address eventForwarder
4646
) public virtual onlyInitializing {
47-
// Initialize base state machine (only if not already initialized)
48-
if (!_secureState.initialized) {
49-
_initializeBaseStateMachine(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
50-
}
51-
47+
_initializeBaseStateMachine(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
48+
5249
// Load RuntimeRBAC-specific definitions
5350
IDefinition.RolePermission memory permissions = RuntimeRBACDefinitions.getRolePermissions();
5451
_loadDefinitions(
@@ -117,68 +114,95 @@ abstract contract RuntimeRBAC is BaseStateMachine, IRuntimeRBAC {
117114
IRuntimeRBAC.RoleConfigAction calldata action = actions[i];
118115

119116
if (action.actionType == IRuntimeRBAC.RoleConfigActionType.CREATE_ROLE) {
120-
// Decode CREATE_ROLE action data
121-
// Format: (string roleName, uint256 maxWallets)
122-
(
123-
string memory roleName,
124-
uint256 maxWallets
125-
) = abi.decode(action.data, (string, uint256));
126-
127-
// Create the role in the secure state with isProtected = false
128-
bytes32 roleHash = _createRole(roleName, maxWallets, false);
129-
130-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.CREATE_ROLE, roleHash, bytes4(0)));
117+
_executeCreateRole(action.data);
131118
} else if (action.actionType == IRuntimeRBAC.RoleConfigActionType.REMOVE_ROLE) {
132-
// Decode REMOVE_ROLE action data
133-
// Format: (bytes32 roleHash)
134-
(bytes32 roleHash) = abi.decode(action.data, (bytes32));
135-
_removeRole(roleHash);
136-
137-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REMOVE_ROLE, roleHash, bytes4(0)));
119+
_executeRemoveRole(action.data);
138120
} else if (action.actionType == IRuntimeRBAC.RoleConfigActionType.ADD_WALLET) {
139-
// Decode ADD_WALLET action data
140-
// Format: (bytes32 roleHash, address wallet)
141-
(bytes32 roleHash, address wallet) = abi.decode(action.data, (bytes32, address));
142-
_requireRoleNotProtected(roleHash);
143-
_assignWallet(roleHash, wallet);
144-
145-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.ADD_WALLET, roleHash, bytes4(0)));
121+
_executeAddWallet(action.data);
146122
} else if (action.actionType == IRuntimeRBAC.RoleConfigActionType.REVOKE_WALLET) {
147-
// Decode REVOKE_WALLET action data
148-
// Format: (bytes32 roleHash, address wallet)
149-
(bytes32 roleHash, address wallet) = abi.decode(action.data, (bytes32, address));
150-
_requireRoleNotProtected(roleHash);
151-
_revokeWallet(roleHash, wallet);
152-
153-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REVOKE_WALLET, roleHash, bytes4(0)));
123+
_executeRevokeWallet(action.data);
154124
} else if (action.actionType == IRuntimeRBAC.RoleConfigActionType.ADD_FUNCTION_TO_ROLE) {
155-
// Decode ADD_FUNCTION_TO_ROLE action data
156-
// Format: (bytes32 roleHash, FunctionPermission functionPermission)
157-
(
158-
bytes32 roleHash,
159-
EngineBlox.FunctionPermission memory functionPermission
160-
) = abi.decode(action.data, (bytes32, EngineBlox.FunctionPermission));
161-
162-
_addFunctionToRole(roleHash, functionPermission);
163-
164-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.ADD_FUNCTION_TO_ROLE, roleHash, functionPermission.functionSelector));
125+
_executeAddFunctionToRole(action.data);
165126
} else if (action.actionType == IRuntimeRBAC.RoleConfigActionType.REMOVE_FUNCTION_FROM_ROLE) {
166-
// Decode REMOVE_FUNCTION_FROM_ROLE action data
167-
// Format: (bytes32 roleHash, bytes4 functionSelector)
168-
(bytes32 roleHash, bytes4 functionSelector) = abi.decode(action.data, (bytes32, bytes4));
169-
_removeFunctionFromRole(roleHash, functionSelector);
170-
171-
_logComponentEvent(_encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REMOVE_FUNCTION_FROM_ROLE, roleHash, functionSelector));
127+
_executeRemoveFunctionFromRole(action.data);
172128
} else {
173129
revert SharedValidation.NotSupported();
174130
}
175131
}
176132
}
177133

178134
/**
179-
* @dev Encodes RBAC config event payload for ComponentEvent. Decode as (RoleConfigActionType, bytes32 roleHash, bytes4 functionSelector).
135+
* @dev Executes CREATE_ROLE: creates a new non-protected role
136+
* @param data ABI-encoded (string roleName, uint256 maxWallets)
137+
*/
138+
function _executeCreateRole(bytes calldata data) internal {
139+
(string memory roleName, uint256 maxWallets) = abi.decode(data, (string, uint256));
140+
bytes32 roleHash = _createRole(roleName, maxWallets, false);
141+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.CREATE_ROLE, roleHash, bytes4(0));
142+
}
143+
144+
/**
145+
* @dev Executes REMOVE_ROLE: removes a role by hash
146+
* @param data ABI-encoded (bytes32 roleHash)
147+
*/
148+
function _executeRemoveRole(bytes calldata data) internal {
149+
(bytes32 roleHash) = abi.decode(data, (bytes32));
150+
_removeRole(roleHash);
151+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REMOVE_ROLE, roleHash, bytes4(0));
152+
}
153+
154+
/**
155+
* @dev Executes ADD_WALLET: assigns a wallet to a role (role must not be protected)
156+
* @param data ABI-encoded (bytes32 roleHash, address wallet)
157+
*/
158+
function _executeAddWallet(bytes calldata data) internal {
159+
(bytes32 roleHash, address wallet) = abi.decode(data, (bytes32, address));
160+
_requireRoleNotProtected(roleHash);
161+
_assignWallet(roleHash, wallet);
162+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.ADD_WALLET, roleHash, bytes4(0));
163+
}
164+
165+
/**
166+
* @dev Executes REVOKE_WALLET: revokes a wallet from a role (role must not be protected)
167+
* @param data ABI-encoded (bytes32 roleHash, address wallet)
168+
*/
169+
function _executeRevokeWallet(bytes calldata data) internal {
170+
(bytes32 roleHash, address wallet) = abi.decode(data, (bytes32, address));
171+
_requireRoleNotProtected(roleHash);
172+
_revokeWallet(roleHash, wallet);
173+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REVOKE_WALLET, roleHash, bytes4(0));
174+
}
175+
176+
/**
177+
* @dev Executes ADD_FUNCTION_TO_ROLE: adds a function permission to a role
178+
* @param data ABI-encoded (bytes32 roleHash, FunctionPermission functionPermission)
179+
*/
180+
function _executeAddFunctionToRole(bytes calldata data) internal {
181+
(
182+
bytes32 roleHash,
183+
EngineBlox.FunctionPermission memory functionPermission
184+
) = abi.decode(data, (bytes32, EngineBlox.FunctionPermission));
185+
_addFunctionToRole(roleHash, functionPermission);
186+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.ADD_FUNCTION_TO_ROLE, roleHash, functionPermission.functionSelector);
187+
}
188+
189+
/**
190+
* @dev Executes REMOVE_FUNCTION_FROM_ROLE: removes a function permission from a role
191+
* @param data ABI-encoded (bytes32 roleHash, bytes4 functionSelector)
192+
*/
193+
function _executeRemoveFunctionFromRole(bytes calldata data) internal {
194+
(bytes32 roleHash, bytes4 functionSelector) = abi.decode(data, (bytes32, bytes4));
195+
_removeFunctionFromRole(roleHash, functionSelector);
196+
_logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType.REMOVE_FUNCTION_FROM_ROLE, roleHash, functionSelector);
197+
}
198+
199+
/**
200+
* @dev Encodes and logs a role config event via ComponentEvent. Payload decodes as (RoleConfigActionType, bytes32 roleHash, bytes4 functionSelector).
201+
* @param action The role config action type
202+
* @param roleHash The role hash
203+
* @param selector The function selector (or zero for N/A)
180204
*/
181-
function _encodeRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType action, bytes32 roleHash, bytes4 selector) internal pure returns (bytes memory) {
182-
return abi.encode(action, roleHash, selector);
205+
function _logRoleConfigEvent(IRuntimeRBAC.RoleConfigActionType action, bytes32 roleHash, bytes4 selector) internal {
206+
_logComponentEvent(abi.encode(action, roleHash, selector));
183207
}
184208
}

contracts/core/base/BaseStateMachine.sol

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,15 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
6565
uint256 timeLockPeriodSec,
6666
address eventForwarder
6767
) internal onlyInitializing {
68-
__ERC165_init();
69-
__ReentrancyGuard_init();
70-
71-
_secureState.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec);
68+
// Skip if already initialized (e.g. when multiple components call from Account.initialize)
69+
if (!_secureState.initialized) {
70+
__ERC165_init();
71+
__ReentrancyGuard_init();
72+
73+
_secureState.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec);
7274

73-
_secureState.setEventForwarder(eventForwarder);
75+
_secureState.setEventForwarder(eventForwarder);
76+
}
7477
}
7578

7679
// ============ SYSTEM ROLE QUERY FUNCTIONS ============
@@ -294,7 +297,6 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
294297
*/
295298
function _setHook(bytes4 functionSelector, address hook) internal {
296299
EngineBlox.addTargetToFunctionHooks(_getSecureState(), functionSelector, hook);
297-
_logComponentEvent(abi.encode(functionSelector, hook));
298300
}
299301

300302
/**
@@ -305,7 +307,6 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
305307
*/
306308
function _clearHook(bytes4 functionSelector, address hook) internal {
307309
EngineBlox.removeTargetFromFunctionHooks(_getSecureState(), functionSelector, hook);
308-
_logComponentEvent(abi.encode(functionSelector, hook));
309310
}
310311

311312
/**

contracts/core/execution/GuardController.sol

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,8 @@ abstract contract GuardController is BaseStateMachine {
7272
uint256 timeLockPeriodSec,
7373
address eventForwarder
7474
) public virtual onlyInitializing {
75-
// Initialize base state machine (only if not already initialized)
76-
if (!_secureState.initialized) {
77-
_initializeBaseStateMachine(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
78-
}
79-
75+
_initializeBaseStateMachine(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
76+
8077
// Load GuardController-specific definitions
8178
IDefinition.RolePermission memory guardControllerPermissions = GuardControllerDefinitions.getRolePermissions();
8279
_loadDefinitions(
@@ -341,56 +338,76 @@ abstract contract GuardController is BaseStateMachine {
341338
IGuardController.GuardConfigAction calldata action = actions[i];
342339

343340
if (action.actionType == IGuardController.GuardConfigActionType.ADD_TARGET_TO_WHITELIST) {
344-
// Decode ADD_TARGET_TO_WHITELIST action data
345-
// Format: (bytes4 functionSelector, address target)
346-
(bytes4 functionSelector, address target) = abi.decode(action.data, (bytes4, address));
347-
348-
_addTargetToFunctionWhitelist(functionSelector, target);
349-
350-
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.ADD_TARGET_TO_WHITELIST, functionSelector, target));
341+
_executeAddTargetToWhitelist(action.data);
351342
} else if (action.actionType == IGuardController.GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST) {
352-
// Decode REMOVE_TARGET_FROM_WHITELIST action data
353-
// Format: (bytes4 functionSelector, address target)
354-
(bytes4 functionSelector, address target) = abi.decode(action.data, (bytes4, address));
355-
356-
_removeTargetFromFunctionWhitelist(functionSelector, target);
357-
358-
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST, functionSelector, target));
343+
_executeRemoveTargetFromWhitelist(action.data);
359344
} else if (action.actionType == IGuardController.GuardConfigActionType.REGISTER_FUNCTION) {
360-
// Decode REGISTER_FUNCTION action data
361-
// Format: (string functionSignature, string operationName, TxAction[] supportedActions)
362-
(
363-
string memory functionSignature,
364-
string memory operationName,
365-
EngineBlox.TxAction[] memory supportedActions
366-
) = abi.decode(action.data, (string, string, EngineBlox.TxAction[]));
367-
368-
bytes4 functionSelector = _registerFunction(functionSignature, operationName, supportedActions);
369-
370-
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.REGISTER_FUNCTION, functionSelector, address(0)));
345+
_executeRegisterFunction(action.data);
371346
} else if (action.actionType == IGuardController.GuardConfigActionType.UNREGISTER_FUNCTION) {
372-
// Decode UNREGISTER_FUNCTION action data
373-
// Format: (bytes4 functionSelector, bool safeRemoval)
374-
(bytes4 functionSelector, bool safeRemoval) = abi.decode(action.data, (bytes4, bool));
375-
376-
_unregisterFunction(functionSelector, safeRemoval);
377-
378-
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.UNREGISTER_FUNCTION, functionSelector, address(0)));
347+
_executeUnregisterFunction(action.data);
379348
} else {
380349
revert SharedValidation.NotSupported();
381350
}
382351
}
383352
}
384353

385354
/**
386-
* @dev Encodes guard config event payload for ComponentEvent. Decode as (GuardConfigActionType, bytes4 functionSelector, address target).
355+
* @dev Executes ADD_TARGET_TO_WHITELIST: adds a target address to a function's call whitelist
356+
* @param data ABI-encoded (bytes4 functionSelector, address target)
357+
*/
358+
function _executeAddTargetToWhitelist(bytes calldata data) internal {
359+
(bytes4 functionSelector, address target) = abi.decode(data, (bytes4, address));
360+
_addTargetToFunctionWhitelist(functionSelector, target);
361+
_logGuardConfigEvent(IGuardController.GuardConfigActionType.ADD_TARGET_TO_WHITELIST, functionSelector, target);
362+
}
363+
364+
/**
365+
* @dev Executes REMOVE_TARGET_FROM_WHITELIST: removes a target address from a function's call whitelist
366+
* @param data ABI-encoded (bytes4 functionSelector, address target)
367+
*/
368+
function _executeRemoveTargetFromWhitelist(bytes calldata data) internal {
369+
(bytes4 functionSelector, address target) = abi.decode(data, (bytes4, address));
370+
_removeTargetFromFunctionWhitelist(functionSelector, target);
371+
_logGuardConfigEvent(IGuardController.GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST, functionSelector, target);
372+
}
373+
374+
/**
375+
* @dev Executes REGISTER_FUNCTION: registers a new function schema with signature, operation name, and supported actions
376+
* @param data ABI-encoded (string functionSignature, string operationName, TxAction[] supportedActions)
377+
*/
378+
function _executeRegisterFunction(bytes calldata data) internal {
379+
(
380+
string memory functionSignature,
381+
string memory operationName,
382+
EngineBlox.TxAction[] memory supportedActions
383+
) = abi.decode(data, (string, string, EngineBlox.TxAction[]));
384+
385+
bytes4 functionSelector = _registerFunction(functionSignature, operationName, supportedActions);
386+
_logGuardConfigEvent(IGuardController.GuardConfigActionType.REGISTER_FUNCTION, functionSelector, address(0));
387+
}
388+
389+
/**
390+
* @dev Executes UNREGISTER_FUNCTION: unregisters a function schema by selector
391+
* @param data ABI-encoded (bytes4 functionSelector, bool safeRemoval)
392+
*/
393+
function _executeUnregisterFunction(bytes calldata data) internal {
394+
(bytes4 functionSelector, bool safeRemoval) = abi.decode(data, (bytes4, bool));
395+
_unregisterFunction(functionSelector, safeRemoval);
396+
_logGuardConfigEvent(IGuardController.GuardConfigActionType.UNREGISTER_FUNCTION, functionSelector, address(0));
397+
}
398+
399+
/**
400+
* @dev Encodes and logs a guard config event via ComponentEvent. Payload decodes as (GuardConfigActionType, bytes4 functionSelector, address target).
401+
* @param actionType The guard config action type
402+
* @param functionSelector The function selector (or zero for N/A)
403+
* @param target The target address (or zero for N/A)
387404
*/
388-
function _encodeGuardConfigEvent(
405+
function _logGuardConfigEvent(
389406
IGuardController.GuardConfigActionType actionType,
390407
bytes4 functionSelector,
391408
address target
392-
) internal pure returns (bytes memory) {
393-
return abi.encode(actionType, functionSelector, target);
409+
) internal {
410+
_logComponentEvent(abi.encode(actionType, functionSelector, target));
394411
}
395412

396413
// ============ INTERNAL FUNCTION SCHEMA HELPERS ============

0 commit comments

Comments
 (0)