@bloxchain/contracts 1.0.0-alpha → 1.0.0-alpha.10
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/README.md +55 -18
- package/abi/{ControlBlox.abi.json → AccountBlox.abi.json} +699 -2974
- package/abi/BareBlox.abi.json +127 -90
- package/abi/BaseStateMachine.abi.json +127 -90
- package/abi/EngineBlox.abi.json +11 -31
- package/abi/GuardController.abi.json +217 -895
- package/abi/GuardControllerDefinitions.abi.json +380 -0
- package/abi/IDefinition.abi.json +19 -0
- package/abi/RoleBlox.abi.json +818 -2404
- package/abi/RuntimeRBAC.abi.json +122 -328
- package/abi/RuntimeRBACDefinitions.abi.json +243 -0
- package/abi/SecureBlox.abi.json +620 -1952
- package/abi/SecureOwnable.abi.json +469 -1801
- package/abi/SecureOwnableDefinitions.abi.json +57 -0
- package/abi/SimpleRWA20.abi.json +486 -1999
- package/abi/SimpleRWA20Definitions.abi.json +19 -0
- package/abi/SimpleVault.abi.json +884 -2685
- package/abi/SimpleVaultDefinitions.abi.json +19 -0
- package/components/README.md +8 -0
- package/core/access/RuntimeRBAC.sol +184 -0
- package/core/access/interface/IRuntimeRBAC.sol +55 -0
- package/{contracts/core → core}/access/lib/definitions/RuntimeRBACDefinitions.sol +121 -1
- package/{contracts/core → core}/base/BaseStateMachine.sol +187 -54
- package/{contracts/core → core}/base/interface/IBaseStateMachine.sol +7 -0
- package/{contracts/core → core}/execution/GuardController.sol +89 -155
- package/{contracts/core → core}/execution/interface/IGuardController.sol +52 -12
- package/{contracts/core → core}/execution/lib/definitions/GuardControllerDefinitions.sol +91 -2
- package/{contracts/core → core}/lib/EngineBlox.sol +167 -64
- package/{contracts → core/lib}/interfaces/IDefinition.sol +15 -6
- package/{contracts → core/lib}/interfaces/IEventForwarder.sol +1 -1
- package/{contracts → core/lib}/utils/SharedValidation.sol +490 -486
- package/core/pattern/Account.sol +75 -0
- package/core/research/BloxchainWallet.sol +133 -0
- package/core/research/FactoryBlox/FactoryBlox.sol +344 -0
- package/core/research/FactoryBlox/FactoryBloxDefinitions.sol +144 -0
- package/core/research/erc1155-blox/ERC1155Blox.sol +170 -0
- package/core/research/erc1155-blox/lib/definitions/ERC1155BloxDefinitions.sol +203 -0
- package/core/research/erc20-blox/ERC20Blox.sol +135 -0
- package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +185 -0
- package/core/research/erc721-blox/ERC721Blox.sol +131 -0
- package/core/research/erc721-blox/lib/definitions/ERC721BloxDefinitions.sol +172 -0
- package/core/research/lending-blox/.gitkeep +1 -0
- package/core/research/p2p-blox/P2PBlox.sol +266 -0
- package/core/research/p2p-blox/README.md +85 -0
- package/core/research/p2p-blox/lib/definitions/P2PBloxDefinitions.sol +19 -0
- package/{contracts/core → core}/security/SecureOwnable.sol +390 -419
- package/{contracts/core → core}/security/interface/ISecureOwnable.sol +27 -40
- package/{contracts/core → core}/security/lib/definitions/SecureOwnableDefinitions.sol +786 -757
- package/package.json +49 -47
- package/standards/README.md +12 -0
- package/standards/behavior/ICopyable.sol +36 -0
- package/standards/hooks/IOnActionHook.sol +21 -0
- package/contracts/core/access/RuntimeRBAC.sol +0 -344
- package/contracts/core/access/interface/IRuntimeRBAC.sol +0 -108
- package/contracts/interfaces/IOnActionHook.sol +0 -79
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
2
|
pragma solidity 0.8.33;
|
|
3
3
|
|
|
4
|
-
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
|
5
4
|
import "../base/BaseStateMachine.sol";
|
|
6
|
-
import "
|
|
5
|
+
import "../lib/utils/SharedValidation.sol";
|
|
7
6
|
import "./lib/definitions/GuardControllerDefinitions.sol";
|
|
8
|
-
import "
|
|
7
|
+
import "../lib/interfaces/IDefinition.sol";
|
|
9
8
|
import "./interface/IGuardController.sol";
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -58,41 +57,6 @@ import "./interface/IGuardController.sol";
|
|
|
58
57
|
abstract contract GuardController is BaseStateMachine {
|
|
59
58
|
using EngineBlox for EngineBlox.SecureOperationState;
|
|
60
59
|
|
|
61
|
-
/**
|
|
62
|
-
* @dev Action types for batched Guard configuration
|
|
63
|
-
*/
|
|
64
|
-
enum GuardConfigActionType {
|
|
65
|
-
ADD_TARGET_TO_WHITELIST,
|
|
66
|
-
REMOVE_TARGET_FROM_WHITELIST,
|
|
67
|
-
REGISTER_FUNCTION,
|
|
68
|
-
UNREGISTER_FUNCTION
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @dev Encodes a single Guard configuration action in a batch
|
|
73
|
-
*/
|
|
74
|
-
struct GuardConfigAction {
|
|
75
|
-
GuardConfigActionType actionType;
|
|
76
|
-
bytes data;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ============ EVENTS ============
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @dev Unified event for all Guard configuration changes applied via batches
|
|
83
|
-
*
|
|
84
|
-
* - actionType: the high-level type of configuration action
|
|
85
|
-
* - functionSelector: affected function selector (if applicable, otherwise 0)
|
|
86
|
-
* - target: affected target address (if applicable, otherwise 0)
|
|
87
|
-
* - data: optional action-specific payload (kept minimal for size; decoded off-chain if needed)
|
|
88
|
-
*/
|
|
89
|
-
event GuardConfigApplied(
|
|
90
|
-
GuardConfigActionType indexed actionType,
|
|
91
|
-
bytes4 indexed functionSelector,
|
|
92
|
-
address indexed target,
|
|
93
|
-
bytes data
|
|
94
|
-
);
|
|
95
|
-
|
|
96
60
|
/**
|
|
97
61
|
* @notice Initializer to initialize GuardController
|
|
98
62
|
* @param initialOwner The initial owner address
|
|
@@ -118,7 +82,8 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
118
82
|
_loadDefinitions(
|
|
119
83
|
GuardControllerDefinitions.getFunctionSchemas(),
|
|
120
84
|
guardControllerPermissions.roleHashes,
|
|
121
|
-
guardControllerPermissions.functionPermissions
|
|
85
|
+
guardControllerPermissions.functionPermissions,
|
|
86
|
+
true // Allow protected schemas for factory settings
|
|
122
87
|
);
|
|
123
88
|
}
|
|
124
89
|
|
|
@@ -155,10 +120,7 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
155
120
|
bytes memory params,
|
|
156
121
|
uint256 gasLimit,
|
|
157
122
|
bytes32 operationType
|
|
158
|
-
) public returns (
|
|
159
|
-
// Validate inputs
|
|
160
|
-
SharedValidation.validateNotZeroAddress(target);
|
|
161
|
-
|
|
123
|
+
) public returns (uint256 txId) {
|
|
162
124
|
// SECURITY: Prevent access to internal execution functions
|
|
163
125
|
_validateNotInternalFunction(target, functionSelector);
|
|
164
126
|
|
|
@@ -172,7 +134,44 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
172
134
|
functionSelector,
|
|
173
135
|
params
|
|
174
136
|
);
|
|
175
|
-
return txRecord;
|
|
137
|
+
return txRecord.txId;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @dev Requests a time-locked execution with payment details attached (same permissions as executeWithTimeLock)
|
|
142
|
+
* @param target The address of the target contract
|
|
143
|
+
* @param value The ETH value to send (0 for standard function calls)
|
|
144
|
+
* @param functionSelector The function selector to execute (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
|
|
145
|
+
* @param params The encoded parameters for the function (empty for simple native token transfers)
|
|
146
|
+
* @param gasLimit The gas limit for execution
|
|
147
|
+
* @param operationType The operation type hash
|
|
148
|
+
* @param paymentDetails The payment details to attach to the transaction
|
|
149
|
+
* @return txId The transaction ID for the requested operation (use getTransaction(txId) for full record)
|
|
150
|
+
* @notice Creates a time-locked transaction with payment that must be approved after the timelock period
|
|
151
|
+
* @notice Reuses EXECUTE_TIME_DELAY_REQUEST permission for the execution selector (no new definitions)
|
|
152
|
+
* @notice Approval/cancel use same flows as executeWithTimeLock (approveTimeLockExecution, cancelTimeLockExecution)
|
|
153
|
+
*/
|
|
154
|
+
function executeWithPayment(
|
|
155
|
+
address target,
|
|
156
|
+
uint256 value,
|
|
157
|
+
bytes4 functionSelector,
|
|
158
|
+
bytes memory params,
|
|
159
|
+
uint256 gasLimit,
|
|
160
|
+
bytes32 operationType,
|
|
161
|
+
EngineBlox.PaymentDetails memory paymentDetails
|
|
162
|
+
) public returns (uint256 txId) {
|
|
163
|
+
_validateNotInternalFunction(target, functionSelector);
|
|
164
|
+
EngineBlox.TxRecord memory txRecord = _requestTransactionWithPayment(
|
|
165
|
+
msg.sender,
|
|
166
|
+
target,
|
|
167
|
+
value,
|
|
168
|
+
gasLimit,
|
|
169
|
+
operationType,
|
|
170
|
+
functionSelector,
|
|
171
|
+
params,
|
|
172
|
+
paymentDetails
|
|
173
|
+
);
|
|
174
|
+
return txRecord.txId;
|
|
176
175
|
}
|
|
177
176
|
|
|
178
177
|
/**
|
|
@@ -183,13 +182,14 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
183
182
|
*/
|
|
184
183
|
function approveTimeLockExecution(
|
|
185
184
|
uint256 txId
|
|
186
|
-
) public returns (
|
|
185
|
+
) public returns (uint256) {
|
|
187
186
|
// SECURITY: Prevent access to internal execution functions
|
|
188
187
|
EngineBlox.TxRecord memory txRecord = _getSecureState().txRecords[txId];
|
|
189
188
|
_validateNotInternalFunction(txRecord.params.target, txRecord.params.executionSelector);
|
|
190
189
|
|
|
191
190
|
// Approve via BaseStateMachine helper (validates permissions and whitelist in EngineBlox)
|
|
192
|
-
|
|
191
|
+
txRecord = _approveTransaction(txId);
|
|
192
|
+
return txRecord.txId;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/**
|
|
@@ -200,13 +200,14 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
200
200
|
*/
|
|
201
201
|
function cancelTimeLockExecution(
|
|
202
202
|
uint256 txId
|
|
203
|
-
) public returns (
|
|
203
|
+
) public returns (uint256) {
|
|
204
204
|
// SECURITY: Prevent access to internal execution functions
|
|
205
205
|
EngineBlox.TxRecord memory txRecord = _getSecureState().txRecords[txId];
|
|
206
206
|
_validateNotInternalFunction(txRecord.params.target, txRecord.params.executionSelector);
|
|
207
207
|
|
|
208
208
|
// Cancel via BaseStateMachine helper (validates permissions in EngineBlox)
|
|
209
|
-
|
|
209
|
+
txRecord = _cancelTransaction(txId);
|
|
210
|
+
return txRecord.txId;
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
/**
|
|
@@ -217,12 +218,13 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
217
218
|
*/
|
|
218
219
|
function approveTimeLockExecutionWithMetaTx(
|
|
219
220
|
EngineBlox.MetaTransaction memory metaTx
|
|
220
|
-
) public returns (
|
|
221
|
+
) public returns (uint256) {
|
|
221
222
|
// SECURITY: Prevent access to internal execution functions
|
|
222
223
|
_validateNotInternalFunction(metaTx.txRecord.params.target, metaTx.txRecord.params.executionSelector);
|
|
223
224
|
|
|
224
225
|
// Approve via BaseStateMachine helper (validates permissions and whitelist in EngineBlox)
|
|
225
|
-
|
|
226
|
+
EngineBlox.TxRecord memory txRecord = _approveTransactionWithMetaTx(metaTx);
|
|
227
|
+
return txRecord.txId;
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
/**
|
|
@@ -233,12 +235,13 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
233
235
|
*/
|
|
234
236
|
function cancelTimeLockExecutionWithMetaTx(
|
|
235
237
|
EngineBlox.MetaTransaction memory metaTx
|
|
236
|
-
) public returns (
|
|
238
|
+
) public returns (uint256) {
|
|
237
239
|
// SECURITY: Prevent access to internal execution functions
|
|
238
240
|
_validateNotInternalFunction(metaTx.txRecord.params.target, metaTx.txRecord.params.executionSelector);
|
|
239
241
|
|
|
240
242
|
// Cancel via BaseStateMachine helper (validates permissions and whitelist in EngineBlox)
|
|
241
|
-
|
|
243
|
+
EngineBlox.TxRecord memory txRecord = _cancelTransactionWithMetaTx(metaTx);
|
|
244
|
+
return txRecord.txId;
|
|
242
245
|
}
|
|
243
246
|
|
|
244
247
|
/**
|
|
@@ -251,12 +254,13 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
251
254
|
*/
|
|
252
255
|
function requestAndApproveExecution(
|
|
253
256
|
EngineBlox.MetaTransaction memory metaTx
|
|
254
|
-
) public returns (
|
|
257
|
+
) public returns (uint256) {
|
|
255
258
|
// SECURITY: Prevent access to internal execution functions
|
|
256
259
|
_validateNotInternalFunction(metaTx.txRecord.params.target, metaTx.txRecord.params.executionSelector);
|
|
257
260
|
|
|
258
261
|
// Request and approve via BaseStateMachine helper (validates permissions and whitelist in EngineBlox)
|
|
259
|
-
|
|
262
|
+
EngineBlox.TxRecord memory txRecord = _requestAndApproveTransaction(metaTx);
|
|
263
|
+
return txRecord.txId;
|
|
260
264
|
}
|
|
261
265
|
|
|
262
266
|
// Note: Meta-transaction utility functions (createMetaTxParams,
|
|
@@ -268,20 +272,6 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
268
272
|
|
|
269
273
|
// ============ INTERNAL VALIDATION HELPERS ============
|
|
270
274
|
|
|
271
|
-
/**
|
|
272
|
-
* @dev Checks if a function selector is a known system macro selector
|
|
273
|
-
* @param functionSelector The function selector to check
|
|
274
|
-
* @return true if the selector is a known system macro selector, false otherwise
|
|
275
|
-
* @notice System macro selectors are special selectors that represent system-level operations
|
|
276
|
-
* and are allowed to bypass certain security restrictions
|
|
277
|
-
* @notice Currently known macro selectors:
|
|
278
|
-
* - NATIVE_TRANSFER_SELECTOR: For native token transfers
|
|
279
|
-
*/
|
|
280
|
-
function _isSystemMacroSelector(bytes4 functionSelector) internal pure returns (bool) {
|
|
281
|
-
return functionSelector == EngineBlox.NATIVE_TRANSFER_SELECTOR
|
|
282
|
-
|| functionSelector == EngineBlox.UPDATE_PAYMENT_SELECTOR;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
275
|
/**
|
|
286
276
|
* @dev Validates that GuardController is not attempting to access internal execution functions
|
|
287
277
|
* @param target The target contract address
|
|
@@ -304,7 +294,7 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
304
294
|
if (target == address(this)) {
|
|
305
295
|
// Allow system macro selectors (e.g., NATIVE_TRANSFER_SELECTOR for native token deposits)
|
|
306
296
|
// These are special system-level operations that are safe to execute on address(this)
|
|
307
|
-
if (
|
|
297
|
+
if (_isMacroSelector(functionSelector)) {
|
|
308
298
|
return; // Allow system macro selectors
|
|
309
299
|
}
|
|
310
300
|
|
|
@@ -315,17 +305,6 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
315
305
|
|
|
316
306
|
// ============ GUARD CONFIGURATION BATCH INTERFACE ============
|
|
317
307
|
|
|
318
|
-
/**
|
|
319
|
-
* @dev Creates execution params for a Guard configuration batch
|
|
320
|
-
* @param actions Encoded guard configuration actions
|
|
321
|
-
* @return The execution params for EngineBlox
|
|
322
|
-
*/
|
|
323
|
-
function guardConfigBatchExecutionParams(
|
|
324
|
-
GuardConfigAction[] memory actions
|
|
325
|
-
) public pure returns (bytes memory) {
|
|
326
|
-
return abi.encode(actions);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
308
|
/**
|
|
330
309
|
* @dev Requests and approves a Guard configuration batch using a meta-transaction
|
|
331
310
|
* @param metaTx The meta-transaction
|
|
@@ -334,19 +313,18 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
334
313
|
*/
|
|
335
314
|
function guardConfigBatchRequestAndApprove(
|
|
336
315
|
EngineBlox.MetaTransaction memory metaTx
|
|
337
|
-
) public returns (
|
|
316
|
+
) public returns (uint256) {
|
|
338
317
|
_validateBroadcaster(msg.sender);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
return _requestAndApproveTransaction(metaTx);
|
|
318
|
+
EngineBlox.TxRecord memory txRecord = _requestAndApproveTransaction(metaTx);
|
|
319
|
+
return txRecord.txId;
|
|
342
320
|
}
|
|
343
321
|
|
|
344
322
|
/**
|
|
345
323
|
* @dev External function that can only be called by the contract itself to execute a Guard configuration batch
|
|
346
324
|
* @param actions Encoded guard configuration actions
|
|
347
325
|
*/
|
|
348
|
-
function executeGuardConfigBatch(GuardConfigAction[] calldata actions) external {
|
|
349
|
-
|
|
326
|
+
function executeGuardConfigBatch(IGuardController.GuardConfigAction[] calldata actions) external {
|
|
327
|
+
_validateExecuteBySelf();
|
|
350
328
|
_executeGuardConfigBatch(actions);
|
|
351
329
|
}
|
|
352
330
|
|
|
@@ -356,43 +334,29 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
356
334
|
* @dev Internal helper to execute a Guard configuration batch
|
|
357
335
|
* @param actions Encoded guard configuration actions
|
|
358
336
|
*/
|
|
359
|
-
function _executeGuardConfigBatch(GuardConfigAction[] calldata actions) internal {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
actions.length,
|
|
363
|
-
EngineBlox.MAX_BATCH_SIZE
|
|
364
|
-
);
|
|
365
|
-
|
|
337
|
+
function _executeGuardConfigBatch(IGuardController.GuardConfigAction[] calldata actions) internal {
|
|
338
|
+
_validateBatchSize(actions.length);
|
|
339
|
+
|
|
366
340
|
for (uint256 i = 0; i < actions.length; i++) {
|
|
367
|
-
GuardConfigAction calldata action = actions[i];
|
|
341
|
+
IGuardController.GuardConfigAction calldata action = actions[i];
|
|
368
342
|
|
|
369
|
-
if (action.actionType == GuardConfigActionType.ADD_TARGET_TO_WHITELIST) {
|
|
343
|
+
if (action.actionType == IGuardController.GuardConfigActionType.ADD_TARGET_TO_WHITELIST) {
|
|
370
344
|
// Decode ADD_TARGET_TO_WHITELIST action data
|
|
371
345
|
// Format: (bytes4 functionSelector, address target)
|
|
372
346
|
(bytes4 functionSelector, address target) = abi.decode(action.data, (bytes4, address));
|
|
373
347
|
|
|
374
348
|
_addTargetToFunctionWhitelist(functionSelector, target);
|
|
375
349
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
functionSelector,
|
|
379
|
-
target,
|
|
380
|
-
"" // optional: could encode additional data if needed
|
|
381
|
-
);
|
|
382
|
-
} else if (action.actionType == GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST) {
|
|
350
|
+
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.ADD_TARGET_TO_WHITELIST, functionSelector, target));
|
|
351
|
+
} else if (action.actionType == IGuardController.GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST) {
|
|
383
352
|
// Decode REMOVE_TARGET_FROM_WHITELIST action data
|
|
384
353
|
// Format: (bytes4 functionSelector, address target)
|
|
385
354
|
(bytes4 functionSelector, address target) = abi.decode(action.data, (bytes4, address));
|
|
386
355
|
|
|
387
356
|
_removeTargetFromFunctionWhitelist(functionSelector, target);
|
|
388
357
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
functionSelector,
|
|
392
|
-
target,
|
|
393
|
-
""
|
|
394
|
-
);
|
|
395
|
-
} else if (action.actionType == GuardConfigActionType.REGISTER_FUNCTION) {
|
|
358
|
+
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST, functionSelector, target));
|
|
359
|
+
} else if (action.actionType == IGuardController.GuardConfigActionType.REGISTER_FUNCTION) {
|
|
396
360
|
// Decode REGISTER_FUNCTION action data
|
|
397
361
|
// Format: (string functionSignature, string operationName, TxAction[] supportedActions)
|
|
398
362
|
(
|
|
@@ -403,31 +367,32 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
403
367
|
|
|
404
368
|
bytes4 functionSelector = _registerFunction(functionSignature, operationName, supportedActions);
|
|
405
369
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
functionSelector,
|
|
409
|
-
address(0),
|
|
410
|
-
"" // optional: abi.encode(operationName)
|
|
411
|
-
);
|
|
412
|
-
} else if (action.actionType == GuardConfigActionType.UNREGISTER_FUNCTION) {
|
|
370
|
+
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.REGISTER_FUNCTION, functionSelector, address(0)));
|
|
371
|
+
} else if (action.actionType == IGuardController.GuardConfigActionType.UNREGISTER_FUNCTION) {
|
|
413
372
|
// Decode UNREGISTER_FUNCTION action data
|
|
414
373
|
// Format: (bytes4 functionSelector, bool safeRemoval)
|
|
415
374
|
(bytes4 functionSelector, bool safeRemoval) = abi.decode(action.data, (bytes4, bool));
|
|
416
375
|
|
|
417
376
|
_unregisterFunction(functionSelector, safeRemoval);
|
|
418
377
|
|
|
419
|
-
|
|
420
|
-
GuardConfigActionType.UNREGISTER_FUNCTION,
|
|
421
|
-
functionSelector,
|
|
422
|
-
address(0),
|
|
423
|
-
""
|
|
424
|
-
);
|
|
378
|
+
_logComponentEvent(_encodeGuardConfigEvent(IGuardController.GuardConfigActionType.UNREGISTER_FUNCTION, functionSelector, address(0)));
|
|
425
379
|
} else {
|
|
426
380
|
revert SharedValidation.NotSupported();
|
|
427
381
|
}
|
|
428
382
|
}
|
|
429
383
|
}
|
|
430
384
|
|
|
385
|
+
/**
|
|
386
|
+
* @dev Encodes guard config event payload for ComponentEvent. Decode as (GuardConfigActionType, bytes4 functionSelector, address target).
|
|
387
|
+
*/
|
|
388
|
+
function _encodeGuardConfigEvent(
|
|
389
|
+
IGuardController.GuardConfigActionType actionType,
|
|
390
|
+
bytes4 functionSelector,
|
|
391
|
+
address target
|
|
392
|
+
) internal pure returns (bytes memory) {
|
|
393
|
+
return abi.encode(actionType, functionSelector, target);
|
|
394
|
+
}
|
|
395
|
+
|
|
431
396
|
// ============ INTERNAL FUNCTION SCHEMA HELPERS ============
|
|
432
397
|
|
|
433
398
|
/**
|
|
@@ -445,16 +410,12 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
445
410
|
// Derive function selector from signature
|
|
446
411
|
functionSelector = bytes4(keccak256(bytes(functionSignature)));
|
|
447
412
|
|
|
448
|
-
// Validate that function schema doesn't already exist
|
|
449
|
-
if (functionSchemaExists(functionSelector)) {
|
|
450
|
-
revert SharedValidation.ResourceAlreadyExists(bytes32(functionSelector));
|
|
451
|
-
}
|
|
452
|
-
|
|
453
413
|
// Convert actions array to bitmap
|
|
454
414
|
uint16 supportedActionsBitmap = _createBitmapFromActions(supportedActions);
|
|
455
415
|
|
|
456
416
|
// Create function schema directly (always non-protected)
|
|
457
417
|
// Dynamically registered functions are execution selectors (handlerForSelectors must contain self-reference)
|
|
418
|
+
// EngineBlox.createFunctionSchema validates schema doesn't already exist (ResourceAlreadyExists)
|
|
458
419
|
bytes4[] memory executionHandlerForSelectors = new bytes4[](1);
|
|
459
420
|
executionHandlerForSelectors[0] = functionSelector; // Self-reference for execution selector
|
|
460
421
|
_createFunctionSchema(
|
|
@@ -471,37 +432,10 @@ abstract contract GuardController is BaseStateMachine {
|
|
|
471
432
|
* @dev Internal helper to unregister a function schema
|
|
472
433
|
* @param functionSelector The function selector to unregister
|
|
473
434
|
* @param safeRemoval If true, checks for role references before removal
|
|
435
|
+
* @notice EngineBlox.removeFunctionSchema validates schema existence (ResourceNotFound) and protected status (CannotModifyProtected)
|
|
474
436
|
*/
|
|
475
437
|
function _unregisterFunction(bytes4 functionSelector, bool safeRemoval) internal {
|
|
476
|
-
// Load schema and validate it exists
|
|
477
|
-
EngineBlox.FunctionSchema storage schema = _getSecureState().functions[functionSelector];
|
|
478
|
-
if (schema.functionSelector != functionSelector) {
|
|
479
|
-
revert SharedValidation.ResourceNotFound(bytes32(functionSelector));
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Ensure not protected
|
|
483
|
-
if (schema.isProtected) {
|
|
484
|
-
revert SharedValidation.CannotModifyProtected(bytes32(functionSelector));
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// The safeRemoval check is now handled within EngineBlox.removeFunctionSchema
|
|
488
|
-
// (avoids getSupportedRolesList/getRoleFunctionPermissions which call _validateAnyRole;
|
|
489
|
-
// during meta-tx execution msg.sender is the contract, causing NoPermission)
|
|
490
438
|
_removeFunctionSchema(functionSelector, safeRemoval);
|
|
491
439
|
}
|
|
492
440
|
|
|
493
|
-
/**
|
|
494
|
-
* @dev Gets all whitelisted targets for a function selector
|
|
495
|
-
* @param functionSelector The function selector
|
|
496
|
-
* @return Array of whitelisted target addresses
|
|
497
|
-
* @notice Requires caller to have any role (via _validateAnyRole) to limit information visibility
|
|
498
|
-
*/
|
|
499
|
-
function getAllowedTargets(
|
|
500
|
-
bytes4 functionSelector
|
|
501
|
-
) external view returns (address[] memory) {
|
|
502
|
-
_validateAnyRole();
|
|
503
|
-
return _getFunctionWhitelistTargets(functionSelector);
|
|
504
|
-
}
|
|
505
441
|
}
|
|
506
|
-
|
|
507
|
-
|
|
@@ -7,11 +7,29 @@ import "../../lib/EngineBlox.sol";
|
|
|
7
7
|
* @title IGuardController
|
|
8
8
|
* @dev Interface for GuardController contract that GuardianSafeV3 and other contracts delegate to
|
|
9
9
|
* @notice This interface defines only GuardController-specific methods
|
|
10
|
-
* @notice Functions from BaseStateMachine (createMetaTxParams, generateUnsignedMetaTransaction*, getTransaction, functionSchemaExists, owner, getBroadcaster, getRecovery) should be accessed via IBaseStateMachine
|
|
11
|
-
* @notice Functions from RuntimeRBAC (registerFunction, unregisterFunction,
|
|
10
|
+
* @notice Functions from BaseStateMachine (createMetaTxParams, generateUnsignedMetaTransaction*, getTransaction, functionSchemaExists, getFunctionSchema, owner, getBroadcaster, getRecovery) should be accessed via IBaseStateMachine
|
|
11
|
+
* @notice Functions from RuntimeRBAC (registerFunction, unregisterFunction, createNewRole, addWalletToRole, revokeWallet) should be accessed via IRuntimeRBAC
|
|
12
12
|
* @custom:security-contact security@particlecrypto.com
|
|
13
13
|
*/
|
|
14
14
|
interface IGuardController {
|
|
15
|
+
/**
|
|
16
|
+
* @dev Action types for batched Guard configuration
|
|
17
|
+
*/
|
|
18
|
+
enum GuardConfigActionType {
|
|
19
|
+
ADD_TARGET_TO_WHITELIST,
|
|
20
|
+
REMOVE_TARGET_FROM_WHITELIST,
|
|
21
|
+
REGISTER_FUNCTION,
|
|
22
|
+
UNREGISTER_FUNCTION
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @dev Encodes a single Guard configuration action in a batch
|
|
27
|
+
*/
|
|
28
|
+
struct GuardConfigAction {
|
|
29
|
+
GuardConfigActionType actionType;
|
|
30
|
+
bytes data;
|
|
31
|
+
}
|
|
32
|
+
|
|
15
33
|
/**
|
|
16
34
|
* @notice Initializer to initialize GuardController
|
|
17
35
|
* @param initialOwner The initial owner address
|
|
@@ -51,63 +69,85 @@ interface IGuardController {
|
|
|
51
69
|
bytes32 operationType
|
|
52
70
|
) external returns (uint256 txId);
|
|
53
71
|
|
|
72
|
+
/**
|
|
73
|
+
* @dev Requests a time-locked execution with payment details attached (same permissions as executeWithTimeLock)
|
|
74
|
+
* @param target The address of the target contract
|
|
75
|
+
* @param value The ETH value to send (0 for standard function calls)
|
|
76
|
+
* @param functionSelector The function selector to execute (NATIVE_TRANSFER_SELECTOR for simple native token transfers)
|
|
77
|
+
* @param params The encoded parameters for the function (empty for simple native token transfers)
|
|
78
|
+
* @param gasLimit The gas limit for execution
|
|
79
|
+
* @param operationType The operation type hash
|
|
80
|
+
* @param paymentDetails The payment details to attach to the transaction
|
|
81
|
+
* @return txId The transaction ID for the requested operation (use getTransaction(txId) for full record)
|
|
82
|
+
* @notice Reuses EXECUTE_TIME_DELAY_REQUEST permission; approval/cancel same as executeWithTimeLock
|
|
83
|
+
*/
|
|
84
|
+
function executeWithPayment(
|
|
85
|
+
address target,
|
|
86
|
+
uint256 value,
|
|
87
|
+
bytes4 functionSelector,
|
|
88
|
+
bytes memory params,
|
|
89
|
+
uint256 gasLimit,
|
|
90
|
+
bytes32 operationType,
|
|
91
|
+
EngineBlox.PaymentDetails memory paymentDetails
|
|
92
|
+
) external returns (uint256 txId);
|
|
93
|
+
|
|
54
94
|
/**
|
|
55
95
|
* @dev Approves and executes a time-locked transaction
|
|
56
96
|
* @param txId The transaction ID
|
|
57
97
|
* @param expectedOperationType The expected operation type for validation
|
|
58
|
-
* @return
|
|
98
|
+
* @return txId The transaction ID (use getTransaction(txId) for full record and result)
|
|
59
99
|
* @notice Requires STANDARD execution type and EXECUTE_TIME_DELAY_APPROVE permission for the execution function
|
|
60
100
|
*/
|
|
61
101
|
function approveTimeLockExecution(
|
|
62
102
|
uint256 txId,
|
|
63
103
|
bytes32 expectedOperationType
|
|
64
|
-
) external returns (
|
|
104
|
+
) external returns (uint256);
|
|
65
105
|
|
|
66
106
|
/**
|
|
67
107
|
* @dev Cancels a time-locked transaction
|
|
68
108
|
* @param txId The transaction ID
|
|
69
109
|
* @param expectedOperationType The expected operation type for validation
|
|
70
|
-
* @return The
|
|
110
|
+
* @return txId The transaction ID (use getTransaction(txId) for full record)
|
|
71
111
|
* @notice Requires STANDARD execution type and EXECUTE_TIME_DELAY_CANCEL permission for the execution function
|
|
72
112
|
*/
|
|
73
113
|
function cancelTimeLockExecution(
|
|
74
114
|
uint256 txId,
|
|
75
115
|
bytes32 expectedOperationType
|
|
76
|
-
) external returns (
|
|
116
|
+
) external returns (uint256);
|
|
77
117
|
|
|
78
118
|
/**
|
|
79
119
|
* @dev Approves a time-locked transaction using a meta-transaction
|
|
80
120
|
* @param metaTx The meta-transaction containing the transaction record and signature
|
|
81
121
|
* @param expectedOperationType The expected operation type for validation
|
|
82
122
|
* @param requiredSelector The handler selector for validation
|
|
83
|
-
* @return The
|
|
123
|
+
* @return The transaction ID (use getTransaction(txId) for full record)
|
|
84
124
|
* @notice Requires STANDARD execution type and EXECUTE_META_APPROVE permission for the execution function
|
|
85
125
|
*/
|
|
86
126
|
function approveTimeLockExecutionWithMetaTx(
|
|
87
127
|
EngineBlox.MetaTransaction memory metaTx,
|
|
88
128
|
bytes32 expectedOperationType,
|
|
89
129
|
bytes4 requiredSelector
|
|
90
|
-
) external returns (
|
|
130
|
+
) external returns (uint256);
|
|
91
131
|
|
|
92
132
|
/**
|
|
93
133
|
* @dev Cancels a time-locked transaction using a meta-transaction
|
|
94
134
|
* @param metaTx The meta-transaction containing the transaction record and signature
|
|
95
135
|
* @param expectedOperationType The expected operation type for validation
|
|
96
136
|
* @param requiredSelector The handler selector for validation
|
|
97
|
-
* @return The
|
|
137
|
+
* @return The transaction ID (use getTransaction(txId) for full record)
|
|
98
138
|
* @notice Requires STANDARD execution type and EXECUTE_META_CANCEL permission for the execution function
|
|
99
139
|
*/
|
|
100
140
|
function cancelTimeLockExecutionWithMetaTx(
|
|
101
141
|
EngineBlox.MetaTransaction memory metaTx,
|
|
102
142
|
bytes32 expectedOperationType,
|
|
103
143
|
bytes4 requiredSelector
|
|
104
|
-
) external returns (
|
|
144
|
+
) external returns (uint256);
|
|
105
145
|
|
|
106
146
|
/**
|
|
107
147
|
* @dev Requests and approves a transaction in one step using a meta-transaction
|
|
108
148
|
* @param metaTx The meta-transaction containing the transaction record and signature
|
|
109
149
|
* @param requiredSelector The handler selector for validation
|
|
110
|
-
* @return The transaction
|
|
150
|
+
* @return The transaction ID (use getTransaction(txId) for full record)
|
|
111
151
|
* @notice Requires STANDARD execution type
|
|
112
152
|
* @notice Validates function schema and permissions for the execution function (same as executeWithTimeLock)
|
|
113
153
|
* @notice Requires EXECUTE_META_REQUEST_AND_APPROVE permission for the execution function selector
|
|
@@ -115,6 +155,6 @@ interface IGuardController {
|
|
|
115
155
|
function requestAndApproveExecution(
|
|
116
156
|
EngineBlox.MetaTransaction memory metaTx,
|
|
117
157
|
bytes4 requiredSelector
|
|
118
|
-
) external returns (
|
|
158
|
+
) external returns (uint256);
|
|
119
159
|
}
|
|
120
160
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
2
|
pragma solidity 0.8.33;
|
|
3
3
|
|
|
4
|
+
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
4
5
|
import "../../../lib/EngineBlox.sol";
|
|
5
|
-
import "
|
|
6
|
+
import "../../../lib/interfaces/IDefinition.sol";
|
|
7
|
+
import "../../interface/IGuardController.sol";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @title GuardControllerDefinitions
|
|
@@ -61,7 +63,7 @@ library GuardControllerDefinitions {
|
|
|
61
63
|
// GuardController: executeGuardConfigBatch((uint8,bytes)[])
|
|
62
64
|
bytes4 public constant GUARD_CONFIG_BATCH_EXECUTE_SELECTOR =
|
|
63
65
|
bytes4(keccak256("executeGuardConfigBatch((uint8,bytes)[])"));
|
|
64
|
-
|
|
66
|
+
|
|
65
67
|
/**
|
|
66
68
|
* @dev Returns predefined function schemas for GuardController execution functions
|
|
67
69
|
* @return Array of function schema definitions
|
|
@@ -398,4 +400,91 @@ library GuardControllerDefinitions {
|
|
|
398
400
|
functionPermissions: functionPermissions
|
|
399
401
|
});
|
|
400
402
|
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* @dev Returns all available GuardConfig action types and their decode formats for discovery.
|
|
406
|
+
* @return actionNames Human-readable action names (same order as GuardConfigActionType enum)
|
|
407
|
+
* @return formats ABI decode format for each action's data, e.g. "(bytes4 functionSelector, address target)"
|
|
408
|
+
* @notice Use with GuardConfigActionType enum: actionNames[i] and formats[i] describe enum value i
|
|
409
|
+
*/
|
|
410
|
+
function getGuardConfigActionSpecs() public pure returns (string[] memory actionNames, string[] memory formats) {
|
|
411
|
+
actionNames = new string[](4);
|
|
412
|
+
formats = new string[](4);
|
|
413
|
+
|
|
414
|
+
actionNames[0] = "ADD_TARGET_TO_WHITELIST";
|
|
415
|
+
formats[0] = "(bytes4 functionSelector, address target)";
|
|
416
|
+
|
|
417
|
+
actionNames[1] = "REMOVE_TARGET_FROM_WHITELIST";
|
|
418
|
+
formats[1] = "(bytes4 functionSelector, address target)";
|
|
419
|
+
|
|
420
|
+
actionNames[2] = "REGISTER_FUNCTION";
|
|
421
|
+
formats[2] = "(string functionSignature, string operationName, TxAction[] supportedActions)";
|
|
422
|
+
|
|
423
|
+
actionNames[3] = "UNREGISTER_FUNCTION";
|
|
424
|
+
formats[3] = "(bytes4 functionSelector, bool safeRemoval)";
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// ============ GUARD CONFIG ACTION DATA ENCODERS ============
|
|
428
|
+
// Use these helpers to build action.data for each GuardConfigActionType without reading the contract.
|
|
429
|
+
// Each encoder returns bytes suitable for GuardConfigAction(actionType, data).
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* @dev Encodes data for ADD_TARGET_TO_WHITELIST. Use with GuardConfigActionType.ADD_TARGET_TO_WHITELIST.
|
|
433
|
+
* @param functionSelector Function whose whitelist is updated
|
|
434
|
+
* @param target Address to add to the whitelist
|
|
435
|
+
*/
|
|
436
|
+
function encodeAddTargetToWhitelist(bytes4 functionSelector, address target) public pure returns (bytes memory) {
|
|
437
|
+
return abi.encode(functionSelector, target);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @dev Encodes data for REMOVE_TARGET_FROM_WHITELIST. Use with GuardConfigActionType.REMOVE_TARGET_FROM_WHITELIST.
|
|
442
|
+
* @param functionSelector Function whose whitelist is updated
|
|
443
|
+
* @param target Address to remove from the whitelist
|
|
444
|
+
*/
|
|
445
|
+
function encodeRemoveTargetFromWhitelist(bytes4 functionSelector, address target) public pure returns (bytes memory) {
|
|
446
|
+
return abi.encode(functionSelector, target);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* @dev Encodes data for REGISTER_FUNCTION. Use with GuardConfigActionType.REGISTER_FUNCTION.
|
|
451
|
+
* @param functionSignature Full function signature string (e.g. "executeWithTimeLock(address,bytes4,bytes,uint256,bytes32)")
|
|
452
|
+
* @param operationName Human-readable operation name
|
|
453
|
+
* @param supportedActions TxActions supported by this function (e.g. EXECUTE_TIME_DELAY_REQUEST)
|
|
454
|
+
*/
|
|
455
|
+
function encodeRegisterFunction(
|
|
456
|
+
string memory functionSignature,
|
|
457
|
+
string memory operationName,
|
|
458
|
+
EngineBlox.TxAction[] memory supportedActions
|
|
459
|
+
) public pure returns (bytes memory) {
|
|
460
|
+
return abi.encode(functionSignature, operationName, supportedActions);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* @dev Encodes data for UNREGISTER_FUNCTION. Use with GuardConfigActionType.UNREGISTER_FUNCTION.
|
|
465
|
+
* @param functionSelector Selector of the function to unregister
|
|
466
|
+
* @param safeRemoval If true, reverts when the function has whitelisted targets
|
|
467
|
+
*/
|
|
468
|
+
function encodeUnregisterFunction(bytes4 functionSelector, bool safeRemoval) public pure returns (bytes memory) {
|
|
469
|
+
return abi.encode(functionSelector, safeRemoval);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* @dev Creates execution params for a Guard configuration batch (pure helper for EngineBlox).
|
|
474
|
+
* @param actions Encoded guard configuration actions (same layout as IGuardController.GuardConfigAction[])
|
|
475
|
+
* @return The execution params for EngineBlox
|
|
476
|
+
*/
|
|
477
|
+
function guardConfigBatchExecutionParams(
|
|
478
|
+
IGuardController.GuardConfigAction[] memory actions
|
|
479
|
+
) public pure returns (bytes memory) {
|
|
480
|
+
return abi.encode(actions);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* @dev ERC165: report support for IDefinition and IERC165 when this library is used at an address.
|
|
485
|
+
* IDefinition extends IERC165; both interface IDs must be reported for ERC165 compliance.
|
|
486
|
+
*/
|
|
487
|
+
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
|
|
488
|
+
return interfaceId == type(IERC165).interfaceId || interfaceId == type(IDefinition).interfaceId;
|
|
489
|
+
}
|
|
401
490
|
}
|