@bloxchain/contracts 1.0.0-alpha.19 → 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.
- package/abi/BaseStateMachine.abi.json +0 -16
- package/abi/EngineBlox.abi.json +46 -4
- package/abi/GuardController.abi.json +28 -7
- package/abi/GuardControllerDefinitions.abi.json +1 -1
- package/abi/RuntimeRBAC.abi.json +28 -7
- package/abi/SecureOwnable.abi.json +23 -7
- package/core/access/RuntimeRBAC.sol +13 -1
- package/core/base/BaseStateMachine.sol +967 -948
- package/core/base/interface/IBaseStateMachine.sol +1 -0
- package/core/execution/GuardController.sol +454 -448
- package/core/execution/lib/definitions/GuardControllerDefinitions.sol +70 -13
- package/core/lib/EngineBlox.sol +182 -38
- package/core/lib/utils/SharedValidation.sol +540 -492
- package/core/security/SecureOwnable.sol +39 -7
- package/package.json +3 -3
|
@@ -1,948 +1,967 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.34;
|
|
3
|
-
|
|
4
|
-
// OpenZeppelin imports
|
|
5
|
-
import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
|
|
6
|
-
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
7
|
-
import "@openzeppelin/contracts
|
|
8
|
-
|
|
9
|
-
// Contracts imports
|
|
10
|
-
import "../lib/EngineBlox.sol";
|
|
11
|
-
import "../lib/utils/SharedValidation.sol";
|
|
12
|
-
import "./interface/IBaseStateMachine.sol";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @title BaseStateMachine
|
|
16
|
-
* @dev Core state machine functionality for secure multi-phase operations
|
|
17
|
-
*
|
|
18
|
-
* This contract provides the foundational state machine capabilities that can be extended
|
|
19
|
-
* by security-specific contracts. It handles:
|
|
20
|
-
* - State initialization and management
|
|
21
|
-
* - Meta-transaction utilities and parameter creation
|
|
22
|
-
* - State queries and transaction history
|
|
23
|
-
* - Role-based access control queries
|
|
24
|
-
* - System state information
|
|
25
|
-
*
|
|
26
|
-
* The contract is designed to be inherited by security-specific contracts that implement
|
|
27
|
-
* their own operation types and business logic while leveraging the core state machine.
|
|
28
|
-
* All access to EngineBlox library functions is centralized through BaseStateMachine
|
|
29
|
-
* wrapper functions to ensure consistency and maintainability.
|
|
30
|
-
*
|
|
31
|
-
* Key Features:
|
|
32
|
-
* - State initialization with role and permission setup
|
|
33
|
-
* - Meta-transaction parameter creation and generation
|
|
34
|
-
* - Comprehensive state queries and transaction history
|
|
35
|
-
* - Role and permission validation utilities
|
|
36
|
-
* - System configuration queries
|
|
37
|
-
* - Event forwarding for external monitoring
|
|
38
|
-
*/
|
|
39
|
-
abstract contract BaseStateMachine is Initializable, ERC165Upgradeable,
|
|
40
|
-
using EngineBlox for EngineBlox.SecureOperationState;
|
|
41
|
-
using SharedValidation for *;
|
|
42
|
-
|
|
43
|
-
EngineBlox.SecureOperationState internal _secureState;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @dev Unified component event for SecureOwnable, GuardController, RuntimeRBAC.
|
|
47
|
-
* Indexers filter by functionSelector (msg.sig at emit site) and decode data (abi-encoded payload).
|
|
48
|
-
* @param functionSelector The function selector (msg.sig) at the emit site; used by indexers to filter
|
|
49
|
-
* @param data ABI-encoded payload associated with the event
|
|
50
|
-
*/
|
|
51
|
-
event ComponentEvent(bytes4 indexed functionSelector, bytes data);
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @notice Initializes the base state machine core
|
|
55
|
-
* @param initialOwner The initial owner address
|
|
56
|
-
* @param broadcaster The broadcaster address
|
|
57
|
-
* @param recovery The recovery address
|
|
58
|
-
* @param timeLockPeriodSec The timelock period in seconds
|
|
59
|
-
* @param eventForwarder The event forwarder address
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
address
|
|
64
|
-
address
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
_secureState.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec);
|
|
74
|
-
|
|
75
|
-
_secureState.setEventForwarder(eventForwarder);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ============ SYSTEM ROLE QUERY FUNCTIONS ============
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @dev Returns the owner of the contract
|
|
83
|
-
* @return The owner of the contract
|
|
84
|
-
*/
|
|
85
|
-
function owner() public view returns (address) {
|
|
86
|
-
return _getAuthorizedWalletAt(EngineBlox.OWNER_ROLE, 0);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @dev Returns all broadcaster addresses for the BROADCASTER_ROLE
|
|
91
|
-
* @return Array of broadcaster addresses
|
|
92
|
-
*/
|
|
93
|
-
function getBroadcasters() public view returns (address[] memory) {
|
|
94
|
-
return _getAuthorizedWallets(EngineBlox.BROADCASTER_ROLE);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @dev Returns the recovery address
|
|
99
|
-
* @return The recovery address
|
|
100
|
-
*/
|
|
101
|
-
function getRecovery() public view returns (address) {
|
|
102
|
-
return _getAuthorizedWalletAt(EngineBlox.RECOVERY_ROLE, 0);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ============ INTERFACE SUPPORT ============
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @dev See {IERC165-supportsInterface}.
|
|
109
|
-
* @notice Base implementation for ERC165 interface detection
|
|
110
|
-
* @notice Registers IBaseStateMachine interface ID for proper interface detection
|
|
111
|
-
* @notice Component contracts (SecureOwnable, RuntimeRBAC, GuardController) should override
|
|
112
|
-
* to add their respective interface IDs for component detection
|
|
113
|
-
*/
|
|
114
|
-
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
|
115
|
-
return interfaceId == type(IBaseStateMachine).interfaceId || super.supportsInterface(interfaceId);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ============ TRANSACTION MANAGEMENT ============
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @dev Centralized function to request a transaction with common validation
|
|
122
|
-
* @param requester The address requesting the transaction
|
|
123
|
-
* @param target The target contract address
|
|
124
|
-
* @param value The ETH value to send (0 for standard function calls)
|
|
125
|
-
* @param gasLimit The gas limit for execution
|
|
126
|
-
* @param operationType The type of operation
|
|
127
|
-
* @param functionSelector The function selector for execution (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
|
|
128
|
-
* @param params The encoded parameters for the function (empty for simple native token transfers)
|
|
129
|
-
* @return The created transaction record
|
|
130
|
-
* @notice Validates permissions for the calling function (request function), not the execution selector
|
|
131
|
-
* @notice Execution functions are internal-only and don't need permission definitions
|
|
132
|
-
* @notice This function is virtual to allow extensions to add hook functionality
|
|
133
|
-
* @notice
|
|
134
|
-
* @notice
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
address
|
|
139
|
-
|
|
140
|
-
uint256
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
* @
|
|
163
|
-
* @param
|
|
164
|
-
* @param
|
|
165
|
-
* @param
|
|
166
|
-
* @param
|
|
167
|
-
* @param
|
|
168
|
-
* @param
|
|
169
|
-
* @param
|
|
170
|
-
* @
|
|
171
|
-
* @
|
|
172
|
-
* @notice
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
address
|
|
177
|
-
|
|
178
|
-
uint256
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
* @
|
|
203
|
-
* @
|
|
204
|
-
* @
|
|
205
|
-
* @notice
|
|
206
|
-
* @notice
|
|
207
|
-
* @notice
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
* @
|
|
220
|
-
* @
|
|
221
|
-
* @
|
|
222
|
-
* @notice
|
|
223
|
-
* @notice
|
|
224
|
-
* @notice
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
* @
|
|
238
|
-
* @
|
|
239
|
-
* @
|
|
240
|
-
* @notice
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
* @
|
|
254
|
-
* @
|
|
255
|
-
* @
|
|
256
|
-
* @notice
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
EngineBlox.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
* @
|
|
271
|
-
* @
|
|
272
|
-
* @
|
|
273
|
-
* @notice
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
* @
|
|
331
|
-
* @param
|
|
332
|
-
* @param
|
|
333
|
-
* @
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
* @
|
|
359
|
-
* @param
|
|
360
|
-
* @param
|
|
361
|
-
* @param
|
|
362
|
-
* @param
|
|
363
|
-
* @
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
* @
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
* @
|
|
464
|
-
* @
|
|
465
|
-
* @
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
* @
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
* @
|
|
699
|
-
* @param
|
|
700
|
-
* @param
|
|
701
|
-
* @
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
bytes4
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
*
|
|
768
|
-
* @param
|
|
769
|
-
*/
|
|
770
|
-
function
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
* @
|
|
795
|
-
*/
|
|
796
|
-
function
|
|
797
|
-
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* @dev
|
|
802
|
-
* @param
|
|
803
|
-
*/
|
|
804
|
-
function
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// ============
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* @dev
|
|
812
|
-
*
|
|
813
|
-
* @
|
|
814
|
-
*/
|
|
815
|
-
function
|
|
816
|
-
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
/**
|
|
820
|
-
* @dev
|
|
821
|
-
* @param
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
* @
|
|
832
|
-
* @
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
* @
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
* @
|
|
852
|
-
* @param
|
|
853
|
-
* @
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
* @
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
// Load
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.34;
|
|
3
|
+
|
|
4
|
+
// OpenZeppelin imports
|
|
5
|
+
import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
|
|
6
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
7
|
+
import "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
|
|
8
|
+
|
|
9
|
+
// Contracts imports
|
|
10
|
+
import "../lib/EngineBlox.sol";
|
|
11
|
+
import "../lib/utils/SharedValidation.sol";
|
|
12
|
+
import "./interface/IBaseStateMachine.sol";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @title BaseStateMachine
|
|
16
|
+
* @dev Core state machine functionality for secure multi-phase operations
|
|
17
|
+
*
|
|
18
|
+
* This contract provides the foundational state machine capabilities that can be extended
|
|
19
|
+
* by security-specific contracts. It handles:
|
|
20
|
+
* - State initialization and management
|
|
21
|
+
* - Meta-transaction utilities and parameter creation
|
|
22
|
+
* - State queries and transaction history
|
|
23
|
+
* - Role-based access control queries
|
|
24
|
+
* - System state information
|
|
25
|
+
*
|
|
26
|
+
* The contract is designed to be inherited by security-specific contracts that implement
|
|
27
|
+
* their own operation types and business logic while leveraging the core state machine.
|
|
28
|
+
* All access to EngineBlox library functions is centralized through BaseStateMachine
|
|
29
|
+
* wrapper functions to ensure consistency and maintainability.
|
|
30
|
+
*
|
|
31
|
+
* Key Features:
|
|
32
|
+
* - State initialization with role and permission setup
|
|
33
|
+
* - Meta-transaction parameter creation and generation
|
|
34
|
+
* - Comprehensive state queries and transaction history
|
|
35
|
+
* - Role and permission validation utilities
|
|
36
|
+
* - System configuration queries
|
|
37
|
+
* - Event forwarding for external monitoring
|
|
38
|
+
*/
|
|
39
|
+
abstract contract BaseStateMachine is Initializable, ERC165Upgradeable, ReentrancyGuardTransient {
|
|
40
|
+
using EngineBlox for EngineBlox.SecureOperationState;
|
|
41
|
+
using SharedValidation for *;
|
|
42
|
+
|
|
43
|
+
EngineBlox.SecureOperationState internal _secureState;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @dev Unified component event for SecureOwnable, GuardController, RuntimeRBAC.
|
|
47
|
+
* Indexers filter by functionSelector (msg.sig at emit site) and decode data (abi-encoded payload).
|
|
48
|
+
* @param functionSelector The function selector (msg.sig) at the emit site; used by indexers to filter
|
|
49
|
+
* @param data ABI-encoded payload associated with the event
|
|
50
|
+
*/
|
|
51
|
+
event ComponentEvent(bytes4 indexed functionSelector, bytes data);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @notice Initializes the base state machine core
|
|
55
|
+
* @param initialOwner The initial owner address
|
|
56
|
+
* @param broadcaster The broadcaster address
|
|
57
|
+
* @param recovery The recovery address
|
|
58
|
+
* @param timeLockPeriodSec The timelock period in seconds
|
|
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.
|
|
61
|
+
*/
|
|
62
|
+
function _initializeBaseStateMachine(
|
|
63
|
+
address initialOwner,
|
|
64
|
+
address broadcaster,
|
|
65
|
+
address recovery,
|
|
66
|
+
uint256 timeLockPeriodSec,
|
|
67
|
+
address eventForwarder
|
|
68
|
+
) internal onlyInitializing {
|
|
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);
|
|
74
|
+
|
|
75
|
+
_secureState.setEventForwarder(eventForwarder);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ============ SYSTEM ROLE QUERY FUNCTIONS ============
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @dev Returns the owner of the contract
|
|
83
|
+
* @return The owner of the contract
|
|
84
|
+
*/
|
|
85
|
+
function owner() public view returns (address) {
|
|
86
|
+
return _getAuthorizedWalletAt(EngineBlox.OWNER_ROLE, 0);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @dev Returns all broadcaster addresses for the BROADCASTER_ROLE
|
|
91
|
+
* @return Array of broadcaster addresses
|
|
92
|
+
*/
|
|
93
|
+
function getBroadcasters() public view returns (address[] memory) {
|
|
94
|
+
return _getAuthorizedWallets(EngineBlox.BROADCASTER_ROLE);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @dev Returns the recovery address
|
|
99
|
+
* @return The recovery address
|
|
100
|
+
*/
|
|
101
|
+
function getRecovery() public view returns (address) {
|
|
102
|
+
return _getAuthorizedWalletAt(EngineBlox.RECOVERY_ROLE, 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ============ INTERFACE SUPPORT ============
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @dev See {IERC165-supportsInterface}.
|
|
109
|
+
* @notice Base implementation for ERC165 interface detection
|
|
110
|
+
* @notice Registers IBaseStateMachine interface ID for proper interface detection
|
|
111
|
+
* @notice Component contracts (SecureOwnable, RuntimeRBAC, GuardController) should override
|
|
112
|
+
* to add their respective interface IDs for component detection
|
|
113
|
+
*/
|
|
114
|
+
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
|
115
|
+
return interfaceId == type(IBaseStateMachine).interfaceId || super.supportsInterface(interfaceId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ============ TRANSACTION MANAGEMENT ============
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @dev Centralized function to request a transaction with common validation
|
|
122
|
+
* @param requester The address requesting the transaction
|
|
123
|
+
* @param target The target contract address
|
|
124
|
+
* @param value The ETH value to send (typically 0 for standard function calls; non-zero is supported for payable edge-case workflows)
|
|
125
|
+
* @param gasLimit The gas limit for execution
|
|
126
|
+
* @param operationType The type of operation
|
|
127
|
+
* @param functionSelector The function selector for execution (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
|
|
128
|
+
* @param params The encoded parameters for the function (empty for simple native token transfers)
|
|
129
|
+
* @return The created transaction record
|
|
130
|
+
* @notice Validates permissions for the calling function (request function), not the execution selector
|
|
131
|
+
* @notice Execution functions are internal-only and don't need permission definitions
|
|
132
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
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=""
|
|
136
|
+
*/
|
|
137
|
+
function _requestTransaction(
|
|
138
|
+
address requester,
|
|
139
|
+
address target,
|
|
140
|
+
uint256 value,
|
|
141
|
+
uint256 gasLimit,
|
|
142
|
+
bytes32 operationType,
|
|
143
|
+
bytes4 functionSelector,
|
|
144
|
+
bytes memory params
|
|
145
|
+
) internal virtual returns (EngineBlox.TxRecord memory) {
|
|
146
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.txRequest(
|
|
147
|
+
_getSecureState(),
|
|
148
|
+
requester,
|
|
149
|
+
target,
|
|
150
|
+
value,
|
|
151
|
+
gasLimit,
|
|
152
|
+
operationType,
|
|
153
|
+
bytes4(msg.sig),
|
|
154
|
+
functionSelector,
|
|
155
|
+
params
|
|
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;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @dev Centralized function to approve a pending transaction after release time
|
|
203
|
+
* @param txId The transaction ID
|
|
204
|
+
* @return The updated transaction record
|
|
205
|
+
* @notice Validates permissions for the calling function (approval function selector), not the execution selector
|
|
206
|
+
* @notice Execution functions are internal-only and don't need permission definitions
|
|
207
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
208
|
+
* @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
|
|
209
|
+
*/
|
|
210
|
+
function _approveTransaction(
|
|
211
|
+
uint256 txId
|
|
212
|
+
) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
|
|
213
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.txDelayedApproval(_getSecureState(), txId, bytes4(msg.sig));
|
|
214
|
+
_postActionHook(txRecord);
|
|
215
|
+
return txRecord;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @dev Centralized function to approve a transaction using meta-transaction
|
|
220
|
+
* @param metaTx The meta-transaction
|
|
221
|
+
* @return The updated transaction record
|
|
222
|
+
* @notice Validates permissions for the calling function (msg.sig) and handler selector from metaTx
|
|
223
|
+
* @notice Uses EXECUTE_META_APPROVE action for permission checking
|
|
224
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
225
|
+
* @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
|
|
226
|
+
*/
|
|
227
|
+
function _approveTransactionWithMetaTx(
|
|
228
|
+
EngineBlox.MetaTransaction memory metaTx
|
|
229
|
+
) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
|
|
230
|
+
_validateMetaTxHandlerBinding(metaTx);
|
|
231
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.txApprovalWithMetaTx(_getSecureState(), metaTx);
|
|
232
|
+
_postActionHook(txRecord);
|
|
233
|
+
return txRecord;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @dev Centralized function to cancel a pending transaction
|
|
238
|
+
* @param txId The transaction ID
|
|
239
|
+
* @return The updated transaction record
|
|
240
|
+
* @notice Validates permissions for the calling function (cancellation function selector), not the execution selector
|
|
241
|
+
* @notice Execution functions are internal-only and don't need permission definitions
|
|
242
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
243
|
+
*/
|
|
244
|
+
function _cancelTransaction(
|
|
245
|
+
uint256 txId
|
|
246
|
+
) internal virtual returns (EngineBlox.TxRecord memory) {
|
|
247
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.txCancellation(_getSecureState(), txId, bytes4(msg.sig));
|
|
248
|
+
_postActionHook(txRecord);
|
|
249
|
+
return txRecord;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @dev Centralized function to cancel a transaction using meta-transaction
|
|
254
|
+
* @param metaTx The meta-transaction
|
|
255
|
+
* @return The updated transaction record
|
|
256
|
+
* @notice Validates permissions for the calling function (msg.sig) and handler selector from metaTx
|
|
257
|
+
* @notice Uses EXECUTE_META_CANCEL action for permission checking
|
|
258
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
259
|
+
*/
|
|
260
|
+
function _cancelTransactionWithMetaTx(
|
|
261
|
+
EngineBlox.MetaTransaction memory metaTx
|
|
262
|
+
) internal virtual returns (EngineBlox.TxRecord memory) {
|
|
263
|
+
_validateMetaTxHandlerBinding(metaTx);
|
|
264
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.txCancellationWithMetaTx(_getSecureState(), metaTx);
|
|
265
|
+
_postActionHook(txRecord);
|
|
266
|
+
return txRecord;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* @dev Centralized function to request and approve a transaction using meta-transaction
|
|
271
|
+
* @param metaTx The meta-transaction
|
|
272
|
+
* @return The transaction record
|
|
273
|
+
* @notice Validates permissions for the calling function (msg.sig) and handler selector from metaTx
|
|
274
|
+
* @notice Uses EXECUTE_META_REQUEST_AND_APPROVE action for permission checking
|
|
275
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
276
|
+
* @notice Protected by ReentrancyGuardTransient to prevent reentrancy attacks
|
|
277
|
+
*/
|
|
278
|
+
function _requestAndApproveTransaction(
|
|
279
|
+
EngineBlox.MetaTransaction memory metaTx
|
|
280
|
+
) internal virtual nonReentrant returns (EngineBlox.TxRecord memory) {
|
|
281
|
+
_validateMetaTxHandlerBinding(metaTx);
|
|
282
|
+
EngineBlox.TxRecord memory txRecord = EngineBlox.requestAndApprove(_getSecureState(), metaTx);
|
|
283
|
+
_postActionHook(txRecord);
|
|
284
|
+
return txRecord;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
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
|
|
291
|
+
*/
|
|
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);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ============ META-TRANSACTION UTILITIES ============
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @dev Creates meta-transaction parameters with specified values
|
|
331
|
+
* @param handlerContract The contract that will handle the meta-transaction
|
|
332
|
+
* @param handlerSelector The function selector for the handler
|
|
333
|
+
* @param action The transaction action type
|
|
334
|
+
* @param deadline The timestamp after which the meta-transaction expires
|
|
335
|
+
* @param maxGasPrice The maximum gas price allowed for execution
|
|
336
|
+
* @param signer The address that will sign the meta-transaction
|
|
337
|
+
* @return The formatted meta-transaction parameters
|
|
338
|
+
*/
|
|
339
|
+
function createMetaTxParams(
|
|
340
|
+
address handlerContract,
|
|
341
|
+
bytes4 handlerSelector,
|
|
342
|
+
EngineBlox.TxAction action,
|
|
343
|
+
uint256 deadline,
|
|
344
|
+
uint256 maxGasPrice,
|
|
345
|
+
address signer
|
|
346
|
+
) public view returns (EngineBlox.MetaTxParams memory) {
|
|
347
|
+
return EngineBlox.createMetaTxParams(
|
|
348
|
+
handlerContract,
|
|
349
|
+
handlerSelector,
|
|
350
|
+
action,
|
|
351
|
+
deadline,
|
|
352
|
+
maxGasPrice,
|
|
353
|
+
signer
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* @dev Generates an unsigned meta-transaction for a new operation
|
|
359
|
+
* @param requester The address requesting the operation
|
|
360
|
+
* @param target The target contract address
|
|
361
|
+
* @param value The ETH value to send
|
|
362
|
+
* @param gasLimit The gas limit for execution
|
|
363
|
+
* @param operationType The type of operation
|
|
364
|
+
* @param executionSelector The function selector to execute (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
|
|
365
|
+
* @param executionParams The encoded parameters for the function (empty for simple native token transfers)
|
|
366
|
+
* @param metaTxParams The meta-transaction parameters
|
|
367
|
+
* @return The unsigned meta-transaction
|
|
368
|
+
*/
|
|
369
|
+
function generateUnsignedMetaTransactionForNew(
|
|
370
|
+
address requester,
|
|
371
|
+
address target,
|
|
372
|
+
uint256 value,
|
|
373
|
+
uint256 gasLimit,
|
|
374
|
+
bytes32 operationType,
|
|
375
|
+
bytes4 executionSelector,
|
|
376
|
+
bytes memory executionParams,
|
|
377
|
+
EngineBlox.MetaTxParams memory metaTxParams
|
|
378
|
+
) public view returns (EngineBlox.MetaTransaction memory) {
|
|
379
|
+
EngineBlox.TxParams memory txParams = EngineBlox.TxParams({
|
|
380
|
+
requester: requester,
|
|
381
|
+
target: target,
|
|
382
|
+
value: value,
|
|
383
|
+
gasLimit: gasLimit,
|
|
384
|
+
operationType: operationType,
|
|
385
|
+
executionSelector: executionSelector,
|
|
386
|
+
executionParams: executionParams
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
return _secureState.generateUnsignedForNewMetaTx(txParams, metaTxParams);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* @dev Generates an unsigned meta-transaction for an existing transaction
|
|
394
|
+
* @param txId The ID of the existing transaction
|
|
395
|
+
* @param metaTxParams The meta-transaction parameters
|
|
396
|
+
* @return The unsigned meta-transaction
|
|
397
|
+
*/
|
|
398
|
+
function generateUnsignedMetaTransactionForExisting(
|
|
399
|
+
uint256 txId,
|
|
400
|
+
EngineBlox.MetaTxParams memory metaTxParams
|
|
401
|
+
) public view returns (EngineBlox.MetaTransaction memory) {
|
|
402
|
+
return _secureState.generateUnsignedForExistingMetaTx(txId, metaTxParams);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// ============ STATE QUERIES ============
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @dev Gets transaction history within a specified range
|
|
409
|
+
* @param fromTxId The starting transaction ID (inclusive)
|
|
410
|
+
* @param toTxId The ending transaction ID (inclusive)
|
|
411
|
+
* @return The transaction history within the specified range
|
|
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).
|
|
415
|
+
*/
|
|
416
|
+
function getTransactionHistory(uint256 fromTxId, uint256 toTxId) public view returns (EngineBlox.TxRecord[] memory) {
|
|
417
|
+
_validateAnyRole();
|
|
418
|
+
|
|
419
|
+
uint256 counter = _secureState.txCounter;
|
|
420
|
+
|
|
421
|
+
// Normalize bounds to valid transaction id range [1, counter]
|
|
422
|
+
fromTxId = fromTxId > 0 ? fromTxId : 1;
|
|
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
|
+
}
|
|
431
|
+
|
|
432
|
+
EngineBlox.TxRecord[] memory history = new EngineBlox.TxRecord[](rangeSize);
|
|
433
|
+
for (uint256 i = 0; i < rangeSize; i++) {
|
|
434
|
+
history[i] = _secureState.getTxRecord(fromTxId + i);
|
|
435
|
+
}
|
|
436
|
+
return history;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* @dev Gets a transaction by ID
|
|
441
|
+
* @param txId The transaction ID
|
|
442
|
+
* @return The transaction record
|
|
443
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
444
|
+
*/
|
|
445
|
+
function getTransaction(uint256 txId) public view returns (EngineBlox.TxRecord memory) {
|
|
446
|
+
_validateAnyRole();
|
|
447
|
+
return _secureState.getTxRecord(txId);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @dev Gets all pending transaction IDs
|
|
452
|
+
* @return Array of pending transaction IDs
|
|
453
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
454
|
+
*/
|
|
455
|
+
function getPendingTransactions() public view returns (uint256[] memory) {
|
|
456
|
+
_validateAnyRole();
|
|
457
|
+
return _secureState.getPendingTransactions();
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// ============ ROLE AND PERMISSION QUERIES ============
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* @dev Gets the basic role information by its hash
|
|
464
|
+
* @param roleHash The hash of the role to get
|
|
465
|
+
* @return roleName The name of the role
|
|
466
|
+
* @return hash The hash of the role
|
|
467
|
+
* @return maxWallets The maximum number of wallets allowed for this role
|
|
468
|
+
* @return walletCount The current number of wallets assigned to this role
|
|
469
|
+
* @return isProtected Whether the role is protected from removal
|
|
470
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
471
|
+
*/
|
|
472
|
+
function getRole(bytes32 roleHash) public view returns (
|
|
473
|
+
string memory roleName,
|
|
474
|
+
bytes32 hash,
|
|
475
|
+
uint256 maxWallets,
|
|
476
|
+
uint256 walletCount,
|
|
477
|
+
bool isProtected
|
|
478
|
+
) {
|
|
479
|
+
_validateAnyRole();
|
|
480
|
+
EngineBlox.Role storage role = _secureState.getRole(roleHash);
|
|
481
|
+
return (
|
|
482
|
+
role.roleName,
|
|
483
|
+
role.roleHash,
|
|
484
|
+
role.maxWallets,
|
|
485
|
+
role.walletCount,
|
|
486
|
+
role.isProtected
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* @dev Returns if a wallet is authorized for a role
|
|
492
|
+
* @param roleHash The hash of the role to check
|
|
493
|
+
* @param wallet The wallet address to check
|
|
494
|
+
* @return True if the wallet is authorized for the role, false otherwise
|
|
495
|
+
*/
|
|
496
|
+
function hasRole(bytes32 roleHash, address wallet) public view returns (bool) {
|
|
497
|
+
return _secureState.hasRole(roleHash, wallet);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* @dev Gets all roles assigned to a wallet
|
|
502
|
+
* @param wallet The wallet address to get roles for
|
|
503
|
+
* @return Array of role hashes assigned to the wallet
|
|
504
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
505
|
+
* @notice This function uses the reverse index for efficient lookup
|
|
506
|
+
*/
|
|
507
|
+
function getWalletRoles(address wallet) public view returns (bytes32[] memory) {
|
|
508
|
+
_validateAnyRole();
|
|
509
|
+
return EngineBlox.getWalletRoles(_getSecureState(), wallet);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* @dev Gets all authorized wallets for a role
|
|
514
|
+
* @param roleHash The role hash to get wallets for
|
|
515
|
+
* @return Array of authorized wallet addresses
|
|
516
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
517
|
+
*/
|
|
518
|
+
function getAuthorizedWallets(bytes32 roleHash) public view returns (address[] memory) {
|
|
519
|
+
_validateAnyRole();
|
|
520
|
+
_validateRoleExists(roleHash);
|
|
521
|
+
return _getAuthorizedWallets(roleHash);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
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
|
|
529
|
+
*/
|
|
530
|
+
function getFunctionSchema(bytes4 functionSelector) external view returns (EngineBlox.FunctionSchema memory) {
|
|
531
|
+
_validateAnyRole();
|
|
532
|
+
return _secureState.getFunctionSchema(functionSelector);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* @dev Gets the function permissions for a specific role
|
|
537
|
+
* @param roleHash The hash of the role to get permissions for
|
|
538
|
+
* @return The function permissions array for the role
|
|
539
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
540
|
+
*/
|
|
541
|
+
function getActiveRolePermissions(bytes32 roleHash) public view returns (EngineBlox.FunctionPermission[] memory) {
|
|
542
|
+
_validateAnyRole();
|
|
543
|
+
return _secureState.getRoleFunctionPermissions(roleHash);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* @dev Gets the current nonce for a specific signer
|
|
548
|
+
* @param signer The address of the signer
|
|
549
|
+
* @return The current nonce for the signer
|
|
550
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
551
|
+
*/
|
|
552
|
+
function getSignerNonce(address signer) public view returns (uint256) {
|
|
553
|
+
_validateAnyRole();
|
|
554
|
+
return _secureState.getSignerNonce(signer);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// ============ SYSTEM STATE QUERIES ============
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* @dev Returns the supported operation types
|
|
561
|
+
* @return The supported operation types
|
|
562
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
563
|
+
*/
|
|
564
|
+
function getSupportedOperationTypes() public view returns (bytes32[] memory) {
|
|
565
|
+
_validateAnyRole();
|
|
566
|
+
return _secureState.getSupportedOperationTypes();
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* @dev Returns the supported roles list
|
|
571
|
+
* @return The supported roles list
|
|
572
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
573
|
+
*/
|
|
574
|
+
function getSupportedRoles() public view returns (bytes32[] memory) {
|
|
575
|
+
_validateAnyRole();
|
|
576
|
+
return _secureState.getSupportedRoles();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* @dev Returns the supported functions list
|
|
581
|
+
* @return The supported functions list
|
|
582
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
583
|
+
*/
|
|
584
|
+
function getSupportedFunctions() public view returns (bytes4[] memory) {
|
|
585
|
+
_validateAnyRole();
|
|
586
|
+
return _secureState.getSupportedFunctions();
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* @dev Returns the time lock period
|
|
591
|
+
* @return The time lock period in seconds
|
|
592
|
+
*/
|
|
593
|
+
function getTimeLockPeriodSec() public view returns (uint256) {
|
|
594
|
+
return _secureState.timeLockPeriodSec;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* @dev Returns whether the contract is initialized
|
|
599
|
+
* @return bool True if the contract is initialized, false otherwise
|
|
600
|
+
*/
|
|
601
|
+
function initialized() public view returns (bool) {
|
|
602
|
+
return _getInitializedVersion() != type(uint8).max && _secureState.initialized;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// ============ ROLE MANAGEMENT ============
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* @dev Centralized function to get authorized wallet at specific index
|
|
609
|
+
* @param roleHash The role hash
|
|
610
|
+
* @param index The wallet index
|
|
611
|
+
* @return The authorized wallet address
|
|
612
|
+
*/
|
|
613
|
+
function _getAuthorizedWalletAt(bytes32 roleHash, uint256 index) internal view returns (address) {
|
|
614
|
+
return EngineBlox.getAuthorizedWalletAt(_getSecureState(), roleHash, index);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* @dev Centralized function to get all authorized wallets for a role
|
|
619
|
+
* @param roleHash The role hash
|
|
620
|
+
* @return Array of authorized wallet addresses
|
|
621
|
+
*/
|
|
622
|
+
function _getAuthorizedWallets(bytes32 roleHash) internal view returns (address[] memory) {
|
|
623
|
+
return EngineBlox.getAuthorizedWallets(_getSecureState(), roleHash);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* @dev Centralized function to create a new role
|
|
628
|
+
* @param roleName The name of the role
|
|
629
|
+
* @param maxWallets The maximum number of wallets allowed for this role
|
|
630
|
+
* @param isProtected Whether the role is protected from removal
|
|
631
|
+
* @return roleHash The hash of the created role
|
|
632
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
633
|
+
*/
|
|
634
|
+
function _createRole(
|
|
635
|
+
string memory roleName,
|
|
636
|
+
uint256 maxWallets,
|
|
637
|
+
bool isProtected
|
|
638
|
+
) internal virtual returns (bytes32) {
|
|
639
|
+
bytes32 roleHash = keccak256(bytes(roleName));
|
|
640
|
+
EngineBlox.createRole(_getSecureState(), roleName, maxWallets, isProtected);
|
|
641
|
+
return roleHash;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* @dev Centralized function to remove a role
|
|
646
|
+
* @param roleHash The hash of the role to remove
|
|
647
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
648
|
+
*/
|
|
649
|
+
function _removeRole(bytes32 roleHash) internal virtual {
|
|
650
|
+
EngineBlox.removeRole(_getSecureState(), roleHash);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* @dev Centralized function to assign a wallet to a role
|
|
655
|
+
* @param roleHash The role hash
|
|
656
|
+
* @param wallet The wallet address to assign
|
|
657
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
658
|
+
*/
|
|
659
|
+
function _assignWallet(bytes32 roleHash, address wallet) internal virtual {
|
|
660
|
+
EngineBlox.assignWallet(_getSecureState(), roleHash, wallet);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* @dev Centralized function to revoke a wallet from a role
|
|
665
|
+
* @param roleHash The role hash
|
|
666
|
+
* @param wallet The wallet address to revoke
|
|
667
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
668
|
+
*/
|
|
669
|
+
function _revokeWallet(bytes32 roleHash, address wallet) internal virtual {
|
|
670
|
+
EngineBlox.revokeWallet(_getSecureState(), roleHash, wallet);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* @dev Centralized function to update wallet for a role (replaces oldWallet with newWallet).
|
|
675
|
+
* @param roleHash The role hash
|
|
676
|
+
* @param newWallet The new wallet address
|
|
677
|
+
* @param oldWallet The old wallet address
|
|
678
|
+
* @notice This function is virtual to allow extensions to add hook functionality or additional validation
|
|
679
|
+
*/
|
|
680
|
+
function _updateWallet(bytes32 roleHash, address newWallet, address oldWallet) internal virtual {
|
|
681
|
+
EngineBlox.updateWallet(_getSecureState(), roleHash, newWallet, oldWallet);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* @dev Centralized function to update the time lock period
|
|
686
|
+
* @param newTimeLockPeriodSec The new time lock period in seconds
|
|
687
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
688
|
+
*/
|
|
689
|
+
function _updateTimeLockPeriod(uint256 newTimeLockPeriodSec) internal virtual {
|
|
690
|
+
uint256 oldPeriod = getTimeLockPeriodSec();
|
|
691
|
+
EngineBlox.updateTimeLockPeriod(_getSecureState(), newTimeLockPeriodSec);
|
|
692
|
+
_logComponentEvent(abi.encode(oldPeriod, newTimeLockPeriodSec));
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// ============ FUNCTION SCHEMA MANAGEMENT ============
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* @dev Centralized function to register a function schema
|
|
699
|
+
* @param functionSignature The function signature
|
|
700
|
+
* @param functionSelector The function selector
|
|
701
|
+
* @param operationName The operation name
|
|
702
|
+
* @param supportedActionsBitmap The bitmap of supported actions
|
|
703
|
+
* @param enforceHandlerRelations Whether to enforce strict handler/schema alignment
|
|
704
|
+
* @param isProtected Whether the function schema is protected
|
|
705
|
+
* @param handlerForSelectors Array of handler selectors
|
|
706
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
707
|
+
*/
|
|
708
|
+
function _registerFunction(
|
|
709
|
+
string memory functionSignature,
|
|
710
|
+
bytes4 functionSelector,
|
|
711
|
+
string memory operationName,
|
|
712
|
+
uint16 supportedActionsBitmap,
|
|
713
|
+
bool enforceHandlerRelations,
|
|
714
|
+
bool isProtected,
|
|
715
|
+
bytes4[] memory handlerForSelectors
|
|
716
|
+
) internal virtual {
|
|
717
|
+
EngineBlox.registerFunction(
|
|
718
|
+
_getSecureState(),
|
|
719
|
+
functionSignature,
|
|
720
|
+
functionSelector,
|
|
721
|
+
operationName,
|
|
722
|
+
supportedActionsBitmap,
|
|
723
|
+
enforceHandlerRelations,
|
|
724
|
+
isProtected,
|
|
725
|
+
handlerForSelectors
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* @dev Centralized function to unregister a function schema
|
|
731
|
+
* @param functionSelector The function selector to unregister
|
|
732
|
+
* @param safeRemoval Whether to perform safe removal (check for role references)
|
|
733
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
734
|
+
*/
|
|
735
|
+
function _unregisterFunction(bytes4 functionSelector, bool safeRemoval) internal virtual {
|
|
736
|
+
EngineBlox.unregisterFunction(_getSecureState(), functionSelector, safeRemoval);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* @dev Centralized function to add a function permission to a role
|
|
741
|
+
* @param roleHash The role hash
|
|
742
|
+
* @param functionPermission The function permission to add
|
|
743
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
744
|
+
*/
|
|
745
|
+
function _addFunctionToRole(
|
|
746
|
+
bytes32 roleHash,
|
|
747
|
+
EngineBlox.FunctionPermission memory functionPermission
|
|
748
|
+
) internal virtual {
|
|
749
|
+
EngineBlox.addFunctionToRole(_getSecureState(), roleHash, functionPermission);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* @dev Centralized function to remove a function permission from a role
|
|
754
|
+
* @param roleHash The role hash
|
|
755
|
+
* @param functionSelector The function selector to remove
|
|
756
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
757
|
+
*/
|
|
758
|
+
function _removeFunctionFromRole(bytes32 roleHash, bytes4 functionSelector) internal virtual {
|
|
759
|
+
EngineBlox.removeFunctionFromRole(_getSecureState(), roleHash, functionSelector);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// ============ PERMISSION VALIDATION ============
|
|
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
|
+
|
|
778
|
+
/**
|
|
779
|
+
* @dev Centralized function to validate that the caller has any role
|
|
780
|
+
*/
|
|
781
|
+
function _validateAnyRole() internal view {
|
|
782
|
+
EngineBlox._validateAnyRole(_getSecureState());
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* @dev Centralized function to validate that a role exists
|
|
787
|
+
* @param roleHash The role hash to validate
|
|
788
|
+
*/
|
|
789
|
+
function _validateRoleExists(bytes32 roleHash) internal view {
|
|
790
|
+
EngineBlox._validateRoleExists(_getSecureState(), roleHash);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* @dev Centralized function to validate that the caller is the contract itself (for execution-only entry points).
|
|
795
|
+
*/
|
|
796
|
+
function _validateExecuteBySelf() internal view {
|
|
797
|
+
SharedValidation.validateInternalCall(address(this));
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* @dev Centralized function to validate batch size against EngineBlox.MAX_BATCH_SIZE.
|
|
802
|
+
* @param length The batch length to validate
|
|
803
|
+
*/
|
|
804
|
+
function _validateBatchSize(uint256 length) internal pure {
|
|
805
|
+
SharedValidation.validateBatchSize(length, EngineBlox.MAX_BATCH_SIZE);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// ============ MACRO SELECTORS ============
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* @dev Adds a function selector to the system macro selectors set.
|
|
812
|
+
* Macro selectors are allowed to target address(this) for system-level operations.
|
|
813
|
+
* @param functionSelector The function selector to add (e.g. NATIVE_TRANSFER_SELECTOR).
|
|
814
|
+
*/
|
|
815
|
+
function _addMacroSelector(bytes4 functionSelector) internal {
|
|
816
|
+
EngineBlox.addMacroSelector(_getSecureState(), functionSelector);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* @dev Returns true if the given function selector is in the system macro selectors set.
|
|
821
|
+
* @param functionSelector The function selector to check.
|
|
822
|
+
*/
|
|
823
|
+
function _isMacroSelector(bytes4 functionSelector) internal view returns (bool) {
|
|
824
|
+
return EngineBlox.isMacroSelector(_getSecureState(), functionSelector);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// ============ UTILITY FUNCTIONS ============
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* @dev Centralized function to convert a bitmap to an array of actions
|
|
831
|
+
* @param bitmap The bitmap to convert
|
|
832
|
+
* @return Array of TxAction values
|
|
833
|
+
*/
|
|
834
|
+
function _convertBitmapToActions(uint16 bitmap) internal pure returns (EngineBlox.TxAction[] memory) {
|
|
835
|
+
return EngineBlox.convertBitmapToActions(bitmap);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* @dev Centralized function to create a bitmap from an array of actions
|
|
840
|
+
* @param actions Array of TxAction values
|
|
841
|
+
* @return The bitmap representation
|
|
842
|
+
*/
|
|
843
|
+
function _createBitmapFromActions(EngineBlox.TxAction[] memory actions) internal pure returns (uint16) {
|
|
844
|
+
return EngineBlox.createBitmapFromActions(actions);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// ============ TARGET WHITELIST MANAGEMENT ============
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @dev Centralized function to add a target address to the whitelist for a function selector
|
|
851
|
+
* @param functionSelector The function selector
|
|
852
|
+
* @param target The target address to whitelist
|
|
853
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
854
|
+
*/
|
|
855
|
+
function _addTargetToWhitelist(bytes4 functionSelector, address target) internal virtual {
|
|
856
|
+
_getSecureState().addTargetToWhitelist(functionSelector, target);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* @dev Centralized function to remove a target address from the whitelist for a function selector
|
|
861
|
+
* @param functionSelector The function selector
|
|
862
|
+
* @param target The target address to remove
|
|
863
|
+
* @notice This function is virtual to allow extensions to add hook functionality
|
|
864
|
+
*/
|
|
865
|
+
function _removeTargetFromWhitelist(bytes4 functionSelector, address target) internal virtual {
|
|
866
|
+
_getSecureState().removeTargetFromWhitelist(functionSelector, target);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* @dev Gets all whitelisted targets for a function selector
|
|
871
|
+
* @param functionSelector The function selector
|
|
872
|
+
* @return Array of whitelisted target addresses
|
|
873
|
+
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
874
|
+
*/
|
|
875
|
+
function getFunctionWhitelistTargets(bytes4 functionSelector) public view returns (address[] memory) {
|
|
876
|
+
_validateAnyRole();
|
|
877
|
+
return _getSecureState().getFunctionWhitelistTargets(functionSelector);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// ============ DEFINITION LOADING ============
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* @dev Loads definitions directly into the secure state
|
|
884
|
+
* This function initializes the secure state with all predefined definitions
|
|
885
|
+
* @param functionSchemas Array of function schema definitions
|
|
886
|
+
* @param roleHashes Array of role hashes
|
|
887
|
+
* @param functionPermissions Array of function permissions (parallel to roleHashes)
|
|
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
|
|
890
|
+
*/
|
|
891
|
+
function _loadDefinitions(
|
|
892
|
+
EngineBlox.FunctionSchema[] memory functionSchemas,
|
|
893
|
+
bytes32[] memory roleHashes,
|
|
894
|
+
EngineBlox.FunctionPermission[] memory functionPermissions,
|
|
895
|
+
bool requireProtected
|
|
896
|
+
) internal {
|
|
897
|
+
// Load function schemas
|
|
898
|
+
for (uint256 i = 0; i < functionSchemas.length; i++) {
|
|
899
|
+
// When enforcing, require every schema to be protected
|
|
900
|
+
if (requireProtected && !functionSchemas[i].isProtected) {
|
|
901
|
+
revert SharedValidation.ContractFunctionMustBeProtected(
|
|
902
|
+
functionSchemas[i].functionSelector
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
_registerFunction(
|
|
906
|
+
functionSchemas[i].functionSignature,
|
|
907
|
+
functionSchemas[i].functionSelector,
|
|
908
|
+
functionSchemas[i].operationName,
|
|
909
|
+
functionSchemas[i].supportedActionsBitmap,
|
|
910
|
+
functionSchemas[i].enforceHandlerRelations,
|
|
911
|
+
functionSchemas[i].isProtected,
|
|
912
|
+
functionSchemas[i].handlerForSelectors
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// Load role permissions using parallel arrays
|
|
917
|
+
SharedValidation.validateArrayLengthMatch(roleHashes.length, functionPermissions.length);
|
|
918
|
+
for (uint256 i = 0; i < roleHashes.length; i++) {
|
|
919
|
+
_addFunctionToRole(roleHashes[i], functionPermissions[i]);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// ============ INTERNAL UTILITIES ============
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* @dev Internal function to get the secure state
|
|
927
|
+
* @return secureState The secure state
|
|
928
|
+
*/
|
|
929
|
+
function _getSecureState() internal view returns (EngineBlox.SecureOperationState storage) {
|
|
930
|
+
return _secureState;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* @dev Internal function to check if an address has action permission
|
|
935
|
+
* @param caller The address to check
|
|
936
|
+
* @param functionSelector The function selector
|
|
937
|
+
* @param action The action to check
|
|
938
|
+
* @return True if the caller has permission, false otherwise
|
|
939
|
+
*/
|
|
940
|
+
function _hasActionPermission(
|
|
941
|
+
address caller,
|
|
942
|
+
bytes4 functionSelector,
|
|
943
|
+
EngineBlox.TxAction action
|
|
944
|
+
) internal view returns (bool) {
|
|
945
|
+
return _secureState.hasActionPermission(caller, functionSelector, action);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* @dev Internal helper to validate that a caller has the BROADCASTER_ROLE
|
|
950
|
+
* @param caller The address to validate
|
|
951
|
+
*/
|
|
952
|
+
function _validateBroadcaster(address caller) internal view {
|
|
953
|
+
if (!hasRole(EngineBlox.BROADCASTER_ROLE, caller)) {
|
|
954
|
+
revert SharedValidation.NoPermission(caller);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* @dev Centralized component event logging for SecureOwnable, GuardController, RuntimeRBAC.
|
|
960
|
+
* Uses msg.sig as the event index so callers only pass encoded data.
|
|
961
|
+
* @param data abi.encode of event parameters
|
|
962
|
+
*/
|
|
963
|
+
function _logComponentEvent(bytes memory data) internal {
|
|
964
|
+
emit ComponentEvent(msg.sig, data);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
}
|