@bloxchain/contracts 1.0.0-alpha.2 → 1.0.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +7 -7
  2. package/abi/BaseStateMachine.abi.json +85 -45
  3. package/abi/EngineBlox.abi.json +73 -90
  4. package/abi/GuardController.abi.json +252 -806
  5. package/abi/{SimpleVaultDefinitions.abi.json → GuardControllerDefinitions.abi.json} +170 -28
  6. package/abi/IDefinition.abi.json +5 -0
  7. package/abi/RuntimeRBAC.abi.json +155 -218
  8. package/abi/RuntimeRBACDefinitions.abi.json +179 -0
  9. package/abi/SecureOwnable.abi.json +524 -1621
  10. package/abi/SecureOwnableDefinitions.abi.json +5 -0
  11. package/components/README.md +8 -0
  12. package/core/access/RuntimeRBAC.sol +255 -270
  13. package/core/access/interface/IRuntimeRBAC.sol +55 -84
  14. package/core/access/lib/definitions/RuntimeRBACDefinitions.sol +93 -2
  15. package/core/base/BaseStateMachine.sol +193 -107
  16. package/core/base/interface/IBaseStateMachine.sol +153 -153
  17. package/core/execution/GuardController.sol +155 -131
  18. package/core/execution/interface/IGuardController.sol +146 -120
  19. package/core/execution/lib/definitions/GuardControllerDefinitions.sol +193 -43
  20. package/core/lib/EngineBlox.sol +2683 -2322
  21. package/{interfaces → core/lib/interfaces}/IDefinition.sol +49 -49
  22. package/{interfaces → core/lib/interfaces}/IEventForwarder.sol +33 -33
  23. package/{utils → core/lib/utils}/SharedValidation.sol +61 -8
  24. package/core/pattern/Account.sol +84 -0
  25. package/core/security/SecureOwnable.sol +456 -412
  26. package/core/security/interface/ISecureOwnable.sol +105 -104
  27. package/core/security/lib/definitions/SecureOwnableDefinitions.sol +22 -6
  28. package/package.json +5 -5
  29. package/standards/README.md +12 -0
  30. package/standards/behavior/ICopyable.sol +34 -0
  31. package/standards/hooks/IOnActionHook.sol +21 -0
  32. package/abi/AccountBlox.abi.json +0 -5799
  33. package/abi/BareBlox.abi.json +0 -1284
  34. package/abi/RoleBlox.abi.json +0 -4209
  35. package/abi/SecureBlox.abi.json +0 -3828
  36. package/abi/SimpleRWA20.abi.json +0 -5288
  37. package/abi/SimpleRWA20Definitions.abi.json +0 -191
  38. package/abi/SimpleVault.abi.json +0 -4951
  39. package/core/research/BloxchainWallet.sol +0 -306
  40. package/core/research/erc20-blox/ERC20Blox.sol +0 -140
  41. package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +0 -185
  42. package/interfaces/IOnActionHook.sol +0 -79
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
- pragma solidity 0.8.33;
2
+ pragma solidity 0.8.34;
3
3
 
4
4
  // OpenZeppelin imports
5
5
  import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
6
6
  import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
7
- import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
7
+ import "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
8
8
 
9
9
  // Contracts imports
10
10
  import "../lib/EngineBlox.sol";
11
- import "../../utils/SharedValidation.sol";
11
+ import "../lib/utils/SharedValidation.sol";
12
12
  import "./interface/IBaseStateMachine.sol";
13
13
 
14
14
  /**
@@ -36,7 +36,7 @@ import "./interface/IBaseStateMachine.sol";
36
36
  * - System configuration queries
37
37
  * - Event forwarding for external monitoring
38
38
  */
39
- abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, ReentrancyGuardUpgradeable {
39
+ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, ReentrancyGuardTransient {
40
40
  using EngineBlox for EngineBlox.SecureOperationState;
41
41
  using SharedValidation for *;
42
42
 
@@ -57,6 +57,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
57
57
  * @param recovery The recovery address
58
58
  * @param timeLockPeriodSec The timelock period in seconds
59
59
  * @param eventForwarder The event forwarder address
60
+ * @dev Reentrancy protection inherits OpenZeppelin {ReentrancyGuardTransient} (EIP-1153 transient storage; requires Cancun+ / configured EVM such as Osaka). No initializer is required.
60
61
  */
61
62
  function _initializeBaseStateMachine(
62
63
  address initialOwner,
@@ -65,12 +66,14 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
65
66
  uint256 timeLockPeriodSec,
66
67
  address eventForwarder
67
68
  ) internal onlyInitializing {
68
- __ERC165_init();
69
- __ReentrancyGuard_init();
70
-
71
- _secureState.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec);
69
+ // Skip if already initialized (e.g. when multiple components call from Account.initialize)
70
+ if (!_secureState.initialized) {
71
+ __ERC165_init();
72
+
73
+ _secureState.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec);
72
74
 
73
- _secureState.setEventForwarder(eventForwarder);
75
+ _secureState.setEventForwarder(eventForwarder);
76
+ }
74
77
  }
75
78
 
76
79
  // ============ SYSTEM ROLE QUERY FUNCTIONS ============
@@ -118,7 +121,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
118
121
  * @dev Centralized function to request a transaction with common validation
119
122
  * @param requester The address requesting the transaction
120
123
  * @param target The target contract address
121
- * @param value The ETH value to send (0 for standard function calls)
124
+ * @param value The ETH value to send (typically 0 for standard function calls; non-zero is supported for payable edge-case workflows)
122
125
  * @param gasLimit The gas limit for execution
123
126
  * @param operationType The type of operation
124
127
  * @param functionSelector The function selector for execution (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
@@ -127,8 +130,9 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
127
130
  * @notice Validates permissions for the calling function (request function), not the execution selector
128
131
  * @notice Execution functions are internal-only and don't need permission definitions
129
132
  * @notice This function is virtual to allow extensions to add hook functionality
130
- * @notice For standard function calls: value=0, functionSelector=non-zero, params=encoded data
131
- * @notice For simple native token transfers: value>0, functionSelector=NATIVE_TRANSFER_SELECTOR, params=""
133
+ * @notice Recommended standard calls: value=0, functionSelector=non-zero, params=encoded data
134
+ * @notice Flexible edge case: non-native selectors may intentionally forward ETH to payable targets
135
+ * @notice Native-only convenience flow: value>0, functionSelector=NATIVE_TRANSFER_SELECTOR, params=""
132
136
  */
133
137
  function _requestTransaction(
134
138
  address requester,
@@ -139,7 +143,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
139
143
  bytes4 functionSelector,
140
144
  bytes memory params
141
145
  ) internal virtual returns (EngineBlox.TxRecord memory) {
142
- return EngineBlox.txRequest(
146
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txRequest(
143
147
  _getSecureState(),
144
148
  requester,
145
149
  target,
@@ -150,6 +154,48 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
150
154
  functionSelector,
151
155
  params
152
156
  );
157
+ _postActionHook(txRecord);
158
+ return txRecord;
159
+ }
160
+
161
+ /**
162
+ * @dev Centralized function to request a transaction with payment details attached from the start
163
+ * @param requester The address requesting the transaction
164
+ * @param target The target contract address
165
+ * @param value The ETH value to send (typically 0 for standard function calls; non-zero is supported for payable edge-case workflows)
166
+ * @param gasLimit The gas limit for execution
167
+ * @param operationType The type of operation
168
+ * @param functionSelector The function selector for execution (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
169
+ * @param params The encoded parameters for the function (empty for simple native token transfers)
170
+ * @param paymentDetails The payment details to attach to the transaction
171
+ * @return The created transaction record with payment set
172
+ * @notice Validates request permissions (same as request without payment)
173
+ * @notice This function is virtual to allow extensions to add hook functionality
174
+ */
175
+ function _requestTransactionWithPayment(
176
+ address requester,
177
+ address target,
178
+ uint256 value,
179
+ uint256 gasLimit,
180
+ bytes32 operationType,
181
+ bytes4 functionSelector,
182
+ bytes memory params,
183
+ EngineBlox.PaymentDetails memory paymentDetails
184
+ ) internal virtual returns (EngineBlox.TxRecord memory) {
185
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txRequestWithPayment(
186
+ _getSecureState(),
187
+ requester,
188
+ target,
189
+ value,
190
+ gasLimit,
191
+ operationType,
192
+ bytes4(msg.sig),
193
+ functionSelector,
194
+ params,
195
+ paymentDetails
196
+ );
197
+ _postActionHook(txRecord);
198
+ return txRecord;
153
199
  }
154
200
 
155
201
  /**
@@ -159,12 +205,14 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
159
205
  * @notice Validates permissions for the calling function (approval function selector), not the execution selector
160
206
  * @notice Execution functions are internal-only and don't need permission definitions
161
207
  * @notice This function is virtual to allow extensions to add hook functionality
162
- * @notice Protected by ReentrancyGuard to prevent reentrancy attacks
208
+ * @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
163
209
  */
164
210
  function _approveTransaction(
165
211
  uint256 txId
166
212
  ) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
167
- return EngineBlox.txDelayedApproval(_getSecureState(), txId, bytes4(msg.sig));
213
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txDelayedApproval(_getSecureState(), txId, bytes4(msg.sig));
214
+ _postActionHook(txRecord);
215
+ return txRecord;
168
216
  }
169
217
 
170
218
  /**
@@ -174,12 +222,15 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
174
222
  * @notice Validates permissions for the calling function (msg.sig) and handler selector from metaTx
175
223
  * @notice Uses EXECUTE_META_APPROVE action for permission checking
176
224
  * @notice This function is virtual to allow extensions to add hook functionality
177
- * @notice Protected by ReentrancyGuard to prevent reentrancy attacks
225
+ * @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
178
226
  */
179
227
  function _approveTransactionWithMetaTx(
180
228
  EngineBlox.MetaTransaction memory metaTx
181
229
  ) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
182
- return EngineBlox.txApprovalWithMetaTx(_getSecureState(), metaTx);
230
+ _validateMetaTxHandlerBinding(metaTx);
231
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txApprovalWithMetaTx(_getSecureState(), metaTx);
232
+ _postActionHook(txRecord);
233
+ return txRecord;
183
234
  }
184
235
 
185
236
  /**
@@ -193,7 +244,9 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
193
244
  function _cancelTransaction(
194
245
  uint256 txId
195
246
  ) internal virtual returns (EngineBlox.TxRecord memory) {
196
- return EngineBlox.txCancellation(_getSecureState(), txId, bytes4(msg.sig));
247
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txCancellation(_getSecureState(), txId, bytes4(msg.sig));
248
+ _postActionHook(txRecord);
249
+ return txRecord;
197
250
  }
198
251
 
199
252
  /**
@@ -207,7 +260,10 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
207
260
  function _cancelTransactionWithMetaTx(
208
261
  EngineBlox.MetaTransaction memory metaTx
209
262
  ) internal virtual returns (EngineBlox.TxRecord memory) {
210
- return EngineBlox.txCancellationWithMetaTx(_getSecureState(), metaTx);
263
+ _validateMetaTxHandlerBinding(metaTx);
264
+ EngineBlox.TxRecord memory txRecord = EngineBlox.txCancellationWithMetaTx(_getSecureState(), metaTx);
265
+ _postActionHook(txRecord);
266
+ return txRecord;
211
267
  }
212
268
 
213
269
  /**
@@ -217,26 +273,55 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
217
273
  * @notice Validates permissions for the calling function (msg.sig) and handler selector from metaTx
218
274
  * @notice Uses EXECUTE_META_REQUEST_AND_APPROVE action for permission checking
219
275
  * @notice This function is virtual to allow extensions to add hook functionality
220
- * @notice Protected by ReentrancyGuard to prevent reentrancy attacks
276
+ * @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
221
277
  */
222
278
  function _requestAndApproveTransaction(
223
279
  EngineBlox.MetaTransaction memory metaTx
224
280
  ) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
225
- return EngineBlox.requestAndApprove(_getSecureState(), metaTx);
281
+ _validateMetaTxHandlerBinding(metaTx);
282
+ EngineBlox.TxRecord memory txRecord = EngineBlox.requestAndApprove(_getSecureState(), metaTx);
283
+ _postActionHook(txRecord);
284
+ return txRecord;
226
285
  }
227
286
 
228
287
  /**
229
- * @dev Centralized function to update payment details for a pending transaction
230
- * @param txId The transaction ID to update payment for
231
- * @param paymentDetails The new payment details
232
- * @notice This function is virtual to allow extensions to add hook functionality
288
+ * @dev Post-action hook invoked after any transaction operation that produces a TxRecord.
289
+ * Override in derived contracts to add centralized post-tx logic (e.g. notifications, side effects).
290
+ * @param txRecord The transaction record produced by the operation
233
291
  */
234
- function _updatePaymentForTransaction(
235
- uint256 txId,
236
- EngineBlox.PaymentDetails memory paymentDetails
237
- ) internal virtual returns (EngineBlox.TxRecord memory) {
238
- EngineBlox.updatePaymentForTransaction(_getSecureState(), txId, paymentDetails);
239
- return _secureState.getTxRecord(txId);
292
+ function _postActionHook(EngineBlox.TxRecord memory txRecord) internal virtual {}
293
+
294
+ // ============ HOOK MANAGEMENT ============
295
+
296
+ /**
297
+ * @dev Sets the hook contract for a function selector (internal; no access control).
298
+ * Extensions (e.g. HookManager) may expose an external setHook with owner check.
299
+ * @param functionSelector The function selector
300
+ * @param hook The hook contract address (must not be zero)
301
+ */
302
+ function _setHook(bytes4 functionSelector, address hook) internal {
303
+ EngineBlox.setHook(_getSecureState(), functionSelector, hook);
304
+ }
305
+
306
+ /**
307
+ * @dev Clears the hook contract for a function selector (internal; no access control).
308
+ * Extensions may expose an external clearHook with owner check.
309
+ * @param functionSelector The function selector
310
+ * @param hook The hook contract address to remove (must not be zero)
311
+ */
312
+ function _clearHook(bytes4 functionSelector, address hook) internal {
313
+ EngineBlox.clearHook(_getSecureState(), functionSelector, hook);
314
+ }
315
+
316
+ /**
317
+ * @dev Returns all configured hooks for a function selector
318
+ * @param functionSelector The function selector
319
+ * @return hooks Array of hook contract addresses
320
+ * @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
321
+ */
322
+ function getHooks(bytes4 functionSelector) public view returns (address[] memory hooks) {
323
+ _validateAnyRole();
324
+ return EngineBlox.getHooks(_getSecureState(), functionSelector);
240
325
  }
241
326
 
242
327
  // ============ META-TRANSACTION UTILITIES ============
@@ -325,28 +410,29 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
325
410
  * @param toTxId The ending transaction ID (inclusive)
326
411
  * @return The transaction history within the specified range
327
412
  * @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
413
+ * @notice Returns an empty array when **`txCounter == 0`** or when the range, after clamping to **1..txCounter**,
414
+ * does not overlap any transaction ids (e.g. `fromTxId` entirely above the current counter).
328
415
  */
329
416
  function getTransactionHistory(uint256 fromTxId, uint256 toTxId) public view returns (EngineBlox.TxRecord[] memory) {
330
417
  _validateAnyRole();
331
-
332
- // Validate the range
418
+
419
+ uint256 counter = _secureState.txCounter;
420
+
421
+ // Normalize bounds to valid transaction id range [1, counter]
333
422
  fromTxId = fromTxId > 0 ? fromTxId : 1;
334
- toTxId = toTxId > _secureState.txCounter ? _secureState.txCounter : toTxId;
335
-
336
- // Validate that fromTxId is less than toTxId
337
- SharedValidation.validateLessThan(fromTxId, toTxId);
423
+ toTxId = toTxId > counter ? counter : toTxId;
424
+
425
+ // Empty history: invalid / non-overlapping clamped range (includes txCounter == 0 → toTxId == 0).
426
+ uint256 rangeSize = fromTxId > toTxId ? 0 : toTxId - fromTxId + 1;
427
+
428
+ if (rangeSize > 0) {
429
+ SharedValidation.validateRangeSize(rangeSize, 1000);
430
+ }
338
431
 
339
- uint256 rangeSize = toTxId - fromTxId + 1;
340
-
341
- // For larger ranges, use paginated version
342
- SharedValidation.validateRangeSize(rangeSize, 1000);
343
-
344
432
  EngineBlox.TxRecord[] memory history = new EngineBlox.TxRecord[](rangeSize);
345
-
346
433
  for (uint256 i = 0; i < rangeSize; i++) {
347
434
  history[i] = _secureState.getTxRecord(fromTxId + i);
348
435
  }
349
-
350
436
  return history;
351
437
  }
352
438
 
@@ -368,7 +454,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
368
454
  */
369
455
  function getPendingTransactions() public view returns (uint256[] memory) {
370
456
  _validateAnyRole();
371
- return _secureState.getPendingTransactionsList();
457
+ return _secureState.getPendingTransactions();
372
458
  }
373
459
 
374
460
  // ============ ROLE AND PERMISSION QUERIES ============
@@ -377,7 +463,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
377
463
  * @dev Gets the basic role information by its hash
378
464
  * @param roleHash The hash of the role to get
379
465
  * @return roleName The name of the role
380
- * @return roleHashReturn The hash of the role
466
+ * @return hash The hash of the role
381
467
  * @return maxWallets The maximum number of wallets allowed for this role
382
468
  * @return walletCount The current number of wallets assigned to this role
383
469
  * @return isProtected Whether the role is protected from removal
@@ -385,7 +471,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
385
471
  */
386
472
  function getRole(bytes32 roleHash) public view returns (
387
473
  string memory roleName,
388
- bytes32 roleHashReturn,
474
+ bytes32 hash,
389
475
  uint256 maxWallets,
390
476
  uint256 walletCount,
391
477
  bool isProtected
@@ -429,29 +515,21 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
429
515
  * @return Array of authorized wallet addresses
430
516
  * @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
431
517
  */
432
- function getWalletsInRole(bytes32 roleHash) public view virtual returns (address[] memory) {
518
+ function getAuthorizedWallets(bytes32 roleHash) public view returns (address[] memory) {
433
519
  _validateAnyRole();
434
520
  _validateRoleExists(roleHash);
435
521
  return _getAuthorizedWallets(roleHash);
436
522
  }
437
523
 
438
524
  /**
439
- * @dev Checks if a function schema exists
440
- * @param functionSelector The function selector to check
441
- * @return True if the function schema exists, false otherwise
442
- */
443
- function functionSchemaExists(bytes4 functionSelector) public view returns (bool) {
444
- return _secureState.functions[functionSelector].functionSelector == functionSelector;
445
- }
446
-
447
- /**
448
- * @dev Returns if an action is supported by a function
449
- * @param functionSelector The function selector to check
450
- * @param action The action to check
451
- * @return True if the action is supported by the function, false otherwise
525
+ * @dev Gets function schema information
526
+ * @param functionSelector The function selector to get information for
527
+ * @return The full FunctionSchema struct (functionSignature, functionSelector, operationType, operationName, supportedActionsBitmap, enforceHandlerRelations, isProtected, handlerForSelectors)
528
+ * @notice Reverts with ResourceNotFound if the schema does not exist
452
529
  */
453
- function isActionSupportedByFunction(bytes4 functionSelector, EngineBlox.TxAction action) public view returns (bool) {
454
- return _secureState.isActionSupportedByFunction(functionSelector, action);
530
+ function getFunctionSchema(bytes4 functionSelector) external view returns (EngineBlox.FunctionSchema memory) {
531
+ _validateAnyRole();
532
+ return _secureState.getFunctionSchema(functionSelector);
455
533
  }
456
534
 
457
535
  /**
@@ -485,7 +563,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
485
563
  */
486
564
  function getSupportedOperationTypes() public view returns (bytes32[] memory) {
487
565
  _validateAnyRole();
488
- return _secureState.getSupportedOperationTypesList();
566
+ return _secureState.getSupportedOperationTypes();
489
567
  }
490
568
 
491
569
  /**
@@ -495,7 +573,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
495
573
  */
496
574
  function getSupportedRoles() public view returns (bytes32[] memory) {
497
575
  _validateAnyRole();
498
- return _secureState.getSupportedRolesList();
576
+ return _secureState.getSupportedRoles();
499
577
  }
500
578
 
501
579
  /**
@@ -505,7 +583,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
505
583
  */
506
584
  function getSupportedFunctions() public view returns (bytes4[] memory) {
507
585
  _validateAnyRole();
508
- return _secureState.getSupportedFunctionsList();
586
+ return _secureState.getSupportedFunctions();
509
587
  }
510
588
 
511
589
  /**
@@ -542,15 +620,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
542
620
  * @return Array of authorized wallet addresses
543
621
  */
544
622
  function _getAuthorizedWallets(bytes32 roleHash) internal view returns (address[] memory) {
545
- EngineBlox.Role storage role = _secureState.roles[roleHash];
546
- uint256 walletCount = role.walletCount;
547
-
548
- address[] memory wallets = new address[](walletCount);
549
- for (uint256 i = 0; i < walletCount; i++) {
550
- wallets[i] = _getAuthorizedWalletAt(roleHash, i);
551
- }
552
-
553
- return wallets;
623
+ return EngineBlox.getAuthorizedWallets(_getSecureState(), roleHash);
554
624
  }
555
625
 
556
626
  /**
@@ -601,14 +671,14 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
601
671
  }
602
672
 
603
673
  /**
604
- * @dev Centralized function to update assigned wallet for a role
674
+ * @dev Centralized function to update wallet for a role (replaces oldWallet with newWallet).
605
675
  * @param roleHash The role hash
606
676
  * @param newWallet The new wallet address
607
677
  * @param oldWallet The old wallet address
608
678
  * @notice This function is virtual to allow extensions to add hook functionality or additional validation
609
679
  */
610
- function _updateAssignedWallet(bytes32 roleHash, address newWallet, address oldWallet) internal virtual {
611
- EngineBlox.updateAssignedWallet(_getSecureState(), roleHash, newWallet, oldWallet);
680
+ function _updateWallet(bytes32 roleHash, address newWallet, address oldWallet) internal virtual {
681
+ EngineBlox.updateWallet(_getSecureState(), roleHash, newWallet, oldWallet);
612
682
  }
613
683
 
614
684
  /**
@@ -617,48 +687,53 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
617
687
  * @notice This function is virtual to allow extensions to add hook functionality
618
688
  */
619
689
  function _updateTimeLockPeriod(uint256 newTimeLockPeriodSec) internal virtual {
690
+ uint256 oldPeriod = getTimeLockPeriodSec();
620
691
  EngineBlox.updateTimeLockPeriod(_getSecureState(), newTimeLockPeriodSec);
692
+ _logComponentEvent(abi.encode(oldPeriod, newTimeLockPeriodSec));
621
693
  }
622
694
 
623
695
  // ============ FUNCTION SCHEMA MANAGEMENT ============
624
696
 
625
697
  /**
626
- * @dev Centralized function to create a function schema
698
+ * @dev Centralized function to register a function schema
627
699
  * @param functionSignature The function signature
628
700
  * @param functionSelector The function selector
629
701
  * @param operationName The operation name
630
702
  * @param supportedActionsBitmap The bitmap of supported actions
703
+ * @param enforceHandlerRelations Whether to enforce strict handler/schema alignment
631
704
  * @param isProtected Whether the function schema is protected
632
705
  * @param handlerForSelectors Array of handler selectors
633
706
  * @notice This function is virtual to allow extensions to add hook functionality
634
707
  */
635
- function _createFunctionSchema(
708
+ function _registerFunction(
636
709
  string memory functionSignature,
637
710
  bytes4 functionSelector,
638
711
  string memory operationName,
639
712
  uint16 supportedActionsBitmap,
713
+ bool enforceHandlerRelations,
640
714
  bool isProtected,
641
715
  bytes4[] memory handlerForSelectors
642
716
  ) internal virtual {
643
- EngineBlox.createFunctionSchema(
717
+ EngineBlox.registerFunction(
644
718
  _getSecureState(),
645
719
  functionSignature,
646
720
  functionSelector,
647
721
  operationName,
648
722
  supportedActionsBitmap,
723
+ enforceHandlerRelations,
649
724
  isProtected,
650
725
  handlerForSelectors
651
726
  );
652
727
  }
653
728
 
654
729
  /**
655
- * @dev Centralized function to remove a function schema
656
- * @param functionSelector The function selector to remove
730
+ * @dev Centralized function to unregister a function schema
731
+ * @param functionSelector The function selector to unregister
657
732
  * @param safeRemoval Whether to perform safe removal (check for role references)
658
733
  * @notice This function is virtual to allow extensions to add hook functionality
659
734
  */
660
- function _removeFunctionSchema(bytes4 functionSelector, bool safeRemoval) internal virtual {
661
- EngineBlox.removeFunctionSchema(_getSecureState(), functionSelector, safeRemoval);
735
+ function _unregisterFunction(bytes4 functionSelector, bool safeRemoval) internal virtual {
736
+ EngineBlox.unregisterFunction(_getSecureState(), functionSelector, safeRemoval);
662
737
  }
663
738
 
664
739
  /**
@@ -686,6 +761,20 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
686
761
 
687
762
  // ============ PERMISSION VALIDATION ============
688
763
 
764
+ /**
765
+ * @dev Binds signed `MetaTxParams` to this wrapper's entrypoint (`msg.sig`) and verifying contract.
766
+ * Must run in `BaseStateMachine` context, not inside linked `EngineBlox` library code (delegatecall
767
+ * would make `msg.sig` refer to the library function, not the outer wrapper).
768
+ * @param metaTx The meta-transaction whose `params` are validated against `msg.sig` and `address(this)`.
769
+ */
770
+ function _validateMetaTxHandlerBinding(EngineBlox.MetaTransaction memory metaTx) internal view {
771
+ SharedValidation.validateMetaTxHandlerSelectorBinding(
772
+ metaTx.params.handlerSelector,
773
+ bytes4(msg.sig)
774
+ );
775
+ SharedValidation.validateMetaTxHandlerContractBinding(metaTx.params.handlerContract);
776
+ }
777
+
689
778
  /**
690
779
  * @dev Centralized function to validate that the caller has any role
691
780
  */
@@ -721,7 +810,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
721
810
  /**
722
811
  * @dev Adds a function selector to the system macro selectors set.
723
812
  * Macro selectors are allowed to target address(this) for system-level operations.
724
- * @param functionSelector The function selector to add (e.g. NATIVE_TRANSFER_SELECTOR, UPDATE_PAYMENT_SELECTOR).
813
+ * @param functionSelector The function selector to add (e.g. NATIVE_TRANSFER_SELECTOR).
725
814
  */
726
815
  function _addMacroSelector(bytes4 functionSelector) internal {
727
816
  EngineBlox.addMacroSelector(_getSecureState(), functionSelector);
@@ -763,8 +852,8 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
763
852
  * @param target The target address to whitelist
764
853
  * @notice This function is virtual to allow extensions to add hook functionality
765
854
  */
766
- function _addTargetToFunctionWhitelist(bytes4 functionSelector, address target) internal virtual {
767
- _getSecureState().addTargetToFunctionWhitelist(functionSelector, target);
855
+ function _addTargetToWhitelist(bytes4 functionSelector, address target) internal virtual {
856
+ _getSecureState().addTargetToWhitelist(functionSelector, target);
768
857
  }
769
858
 
770
859
  /**
@@ -773,16 +862,18 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
773
862
  * @param target The target address to remove
774
863
  * @notice This function is virtual to allow extensions to add hook functionality
775
864
  */
776
- function _removeTargetFromFunctionWhitelist(bytes4 functionSelector, address target) internal virtual {
777
- _getSecureState().removeTargetFromFunctionWhitelist(functionSelector, target);
865
+ function _removeTargetFromWhitelist(bytes4 functionSelector, address target) internal virtual {
866
+ _getSecureState().removeTargetFromWhitelist(functionSelector, target);
778
867
  }
779
868
 
780
869
  /**
781
- * @dev Centralized function to get all whitelisted targets for a function selector
870
+ * @dev Gets all whitelisted targets for a function selector
782
871
  * @param functionSelector The function selector
783
872
  * @return Array of whitelisted target addresses
873
+ * @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
784
874
  */
785
- function _getFunctionWhitelistTargets(bytes4 functionSelector) internal view returns (address[] memory) {
875
+ function getFunctionWhitelistTargets(bytes4 functionSelector) public view returns (address[] memory) {
876
+ _validateAnyRole();
786
877
  return _getSecureState().getFunctionWhitelistTargets(functionSelector);
787
878
  }
788
879
 
@@ -794,30 +885,29 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
794
885
  * @param functionSchemas Array of function schema definitions
795
886
  * @param roleHashes Array of role hashes
796
887
  * @param functionPermissions Array of function permissions (parallel to roleHashes)
797
- * @param allowProtectedSchemas Whether to allow protected function schemas (default: true for factory settings)
798
- * @notice When allowProtectedSchemas is false, reverts if any function schema is protected
799
- * @notice This allows custom definitions to be restricted from creating protected schemas
888
+ * @param requireProtected When true, all function schemas must be protected; reverts if any is not
889
+ * @notice When requireProtected is true, every function schema must have isProtected == true
800
890
  */
801
891
  function _loadDefinitions(
802
892
  EngineBlox.FunctionSchema[] memory functionSchemas,
803
893
  bytes32[] memory roleHashes,
804
894
  EngineBlox.FunctionPermission[] memory functionPermissions,
805
- bool allowProtectedSchemas
895
+ bool requireProtected
806
896
  ) internal {
807
897
  // Load function schemas
808
898
  for (uint256 i = 0; i < functionSchemas.length; i++) {
809
- // Validate protected schemas if not allowed (for custom definitions)
810
- if (!allowProtectedSchemas && functionSchemas[i].isProtected) {
811
- revert SharedValidation.CannotModifyProtected(
812
- bytes32(functionSchemas[i].functionSelector)
899
+ // When enforcing, require every schema to be protected
900
+ if (requireProtected && !functionSchemas[i].isProtected) {
901
+ revert SharedValidation.ContractFunctionMustBeProtected(
902
+ functionSchemas[i].functionSelector
813
903
  );
814
904
  }
815
- EngineBlox.createFunctionSchema(
816
- _getSecureState(),
905
+ _registerFunction(
817
906
  functionSchemas[i].functionSignature,
818
907
  functionSchemas[i].functionSelector,
819
908
  functionSchemas[i].operationName,
820
909
  functionSchemas[i].supportedActionsBitmap,
910
+ functionSchemas[i].enforceHandlerRelations,
821
911
  functionSchemas[i].isProtected,
822
912
  functionSchemas[i].handlerForSelectors
823
913
  );
@@ -826,11 +916,7 @@ abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, Reentran
826
916
  // Load role permissions using parallel arrays
827
917
  SharedValidation.validateArrayLengthMatch(roleHashes.length, functionPermissions.length);
828
918
  for (uint256 i = 0; i < roleHashes.length; i++) {
829
- EngineBlox.addFunctionToRole(
830
- _getSecureState(),
831
- roleHashes[i],
832
- functionPermissions[i]
833
- );
919
+ _addFunctionToRole(roleHashes[i], functionPermissions[i]);
834
920
  }
835
921
  }
836
922