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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +7 -7
  2. package/abi/BaseStateMachine.abi.json +798 -753
  3. package/abi/EngineBlox.abi.json +566 -576
  4. package/abi/GuardController.abi.json +1546 -2095
  5. package/abi/GuardControllerDefinitions.abi.json +416 -0
  6. package/abi/IDefinition.abi.json +57 -47
  7. package/abi/RuntimeRBAC.abi.json +901 -959
  8. package/abi/RuntimeRBACDefinitions.abi.json +265 -81
  9. package/abi/SecureOwnable.abi.json +1522 -2581
  10. package/abi/SecureOwnableDefinitions.abi.json +174 -164
  11. package/components/README.md +8 -0
  12. package/core/access/RuntimeRBAC.sol +253 -270
  13. package/core/access/interface/IRuntimeRBAC.sol +55 -84
  14. package/core/access/lib/definitions/RuntimeRBACDefinitions.sol +97 -4
  15. package/core/base/BaseStateMachine.sol +198 -108
  16. package/core/base/interface/IBaseStateMachine.sol +153 -153
  17. package/core/execution/GuardController.sol +156 -131
  18. package/core/execution/interface/IGuardController.sol +146 -120
  19. package/core/execution/lib/definitions/GuardControllerDefinitions.sol +207 -45
  20. package/core/lib/EngineBlox.sol +2636 -2322
  21. package/{interfaces → core/lib/interfaces}/IDefinition.sol +49 -49
  22. package/{interfaces → core/lib/interfaces}/IEventForwarder.sol +5 -3
  23. package/{utils → core/lib/utils}/SharedValidation.sol +69 -22
  24. package/core/pattern/Account.sol +84 -0
  25. package/core/security/SecureOwnable.sol +180 -146
  26. package/core/security/interface/ISecureOwnable.sol +105 -104
  27. package/core/security/lib/definitions/SecureOwnableDefinitions.sol +818 -786
  28. package/package.json +5 -5
  29. package/standards/README.md +12 -0
  30. package/standards/behavior/ICopyable.sol +34 -0
  31. package/standards/hooks/IOnActionHook.sol +21 -0
  32. package/abi/AccountBlox.abi.json +0 -5799
  33. package/abi/BareBlox.abi.json +0 -1284
  34. package/abi/RoleBlox.abi.json +0 -4209
  35. package/abi/SecureBlox.abi.json +0 -3828
  36. package/abi/SimpleRWA20.abi.json +0 -5288
  37. package/abi/SimpleRWA20Definitions.abi.json +0 -191
  38. package/abi/SimpleVault.abi.json +0 -4951
  39. package/abi/SimpleVaultDefinitions.abi.json +0 -269
  40. package/core/research/BloxchainWallet.sol +0 -306
  41. package/core/research/erc20-blox/ERC20Blox.sol +0 -140
  42. package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +0 -185
  43. package/interfaces/IOnActionHook.sol +0 -79
@@ -1,49 +1,49 @@
1
- // SPDX-License-Identifier: MPL-2.0
2
- pragma solidity 0.8.33;
3
-
4
- import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
5
- import "../core/lib/EngineBlox.sol";
6
-
7
- /**
8
- * @dev Interface for definition contracts that provide operation types, function schemas, and role permissions
9
- *
10
- * This interface allows contracts to dynamically load their configuration from external
11
- * definition contracts, enabling modular and extensible contract initialization.
12
- *
13
- * Definition contracts (or deployed definition libraries) used by address should implement
14
- * ERC165 and return true for type(IDefinition).interfaceId so consumers can validate
15
- * before calling getFunctionSchemas() / getRolePermissions().
16
- *
17
- * Definition contracts should implement this interface to provide:
18
- * - Operation type definitions (what operations are supported)
19
- * - Function schema definitions (how functions are structured)
20
- * - Role permission definitions (who can do what)
21
- */
22
- interface IDefinition is IERC165 {
23
- /**
24
- * @dev Struct to hold role permission data
25
- * @param roleHashes Array of role hashes
26
- * @param functionPermissions Array of function permissions (parallel to roleHashes)
27
- */
28
- struct RolePermission {
29
- bytes32[] roleHashes;
30
- EngineBlox.FunctionPermission[] functionPermissions;
31
- }
32
-
33
- /**
34
- * @dev Returns all function schema definitions
35
- * @return Array of function schema definitions
36
- */
37
- function getFunctionSchemas() external pure returns (EngineBlox.FunctionSchema[] memory);
38
-
39
- /**
40
- * @dev Returns all role hashes and their corresponding function permissions
41
- * @return RolePermission struct containing roleHashes and functionPermissions arrays
42
- */
43
- function getRolePermissions() external pure returns (RolePermission memory);
44
-
45
- /**
46
- * @dev ERC165: return true for type(IDefinition).interfaceId
47
- */
48
- function supportsInterface(bytes4 interfaceId) external view returns (bool);
49
- }
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ pragma solidity 0.8.35;
3
+
4
+ import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
5
+ import "../EngineBlox.sol";
6
+
7
+ /**
8
+ * @dev Interface for definition contracts that provide operation types, function schemas, and role permissions
9
+ *
10
+ * This interface allows contracts to dynamically load their configuration from external
11
+ * definition contracts, enabling modular and extensible contract initialization.
12
+ *
13
+ * Definition contracts (or deployed definition libraries) used by address should implement
14
+ * ERC165 and return true for type(IDefinition).interfaceId so consumers can validate
15
+ * before calling getFunctionSchemas() / getRolePermissions().
16
+ *
17
+ * Definition contracts should implement this interface to provide:
18
+ * - Operation type definitions (what operations are supported)
19
+ * - Function schema definitions (how functions are structured)
20
+ * - Role permission definitions (who can do what)
21
+ */
22
+ interface IDefinition is IERC165 {
23
+ /**
24
+ * @dev Struct to hold role permission data
25
+ * @param roleHashes Array of role hashes
26
+ * @param functionPermissions Array of function permissions (parallel to roleHashes)
27
+ */
28
+ struct RolePermission {
29
+ bytes32[] roleHashes;
30
+ EngineBlox.FunctionPermission[] functionPermissions;
31
+ }
32
+
33
+ /**
34
+ * @dev Returns all function schema definitions
35
+ * @return Array of function schema definitions
36
+ */
37
+ function getFunctionSchemas() external pure returns (EngineBlox.FunctionSchema[] memory);
38
+
39
+ /**
40
+ * @dev Returns all role hashes and their corresponding function permissions
41
+ * @return RolePermission struct containing roleHashes and functionPermissions arrays
42
+ */
43
+ function getRolePermissions() external pure returns (RolePermission memory);
44
+
45
+ /**
46
+ * @dev ERC165: return true for type(IDefinition).interfaceId
47
+ */
48
+ function supportsInterface(bytes4 interfaceId) external view returns (bool);
49
+ }
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
- pragma solidity 0.8.33;
2
+ pragma solidity 0.8.35;
3
3
 
4
4
  // Import TxRecord struct from EngineBlox
5
- import "../core/lib/EngineBlox.sol";
5
+ import "../EngineBlox.sol";
6
6
 
7
7
  /**
8
8
  * @title IEventForwarder
@@ -21,6 +21,7 @@ interface IEventForwarder {
21
21
  * @param requester The address of the requester
22
22
  * @param target The target contract address
23
23
  * @param operationType The type of operation
24
+ * @param resultHash Commitment to execution returndata (`bytes32(0)` when none). Full bytes: `TxExecutionResult` log.
24
25
  */
25
26
  function forwardTxEvent(
26
27
  uint256 txId,
@@ -28,6 +29,7 @@ interface IEventForwarder {
28
29
  EngineBlox.TxStatus status,
29
30
  address requester,
30
31
  address target,
31
- bytes32 operationType
32
+ bytes32 operationType,
33
+ bytes32 resultHash
32
34
  ) external;
33
35
  }
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
- pragma solidity 0.8.33;
2
+ pragma solidity 0.8.35;
3
3
 
4
4
  /**
5
5
  * @title SharedValidation
@@ -38,7 +38,6 @@ library SharedValidation {
38
38
  // Time and deadline errors with context
39
39
  error InvalidTimeLockPeriod(uint256 provided);
40
40
  error TimeLockPeriodZero(uint256 provided);
41
- error DeadlineInPast(uint256 deadline, uint256 currentTime);
42
41
  error MetaTxExpired(uint256 deadline, uint256 currentTime);
43
42
  error BeforeReleaseTime(uint256 releaseTime, uint256 currentTime);
44
43
  error NewTimelockSame(uint256 newPeriod, uint256 currentPeriod);
@@ -51,6 +50,8 @@ library SharedValidation {
51
50
  error RestrictedRecovery(address caller, address recovery);
52
51
  error RestrictedBroadcaster(address caller, address broadcaster);
53
52
  error SignerNotAuthorized(address signer);
53
+ error MetaTxHandlerSelectorMismatch(bytes4 signedSelector, bytes4 entrySelector);
54
+ error MetaTxHandlerContractMismatch(address signedContract, address entryContract);
54
55
  error OnlyCallableByContract(address caller, address contractAddress);
55
56
 
56
57
  // Transaction and operation errors with context
@@ -59,6 +60,7 @@ library SharedValidation {
59
60
  error ZeroOperationTypeNotAllowed();
60
61
  error TransactionStatusMismatch(uint8 expectedStatus, uint8 currentStatus);
61
62
  error AlreadyInitialized();
63
+ error NotInitialized();
62
64
  error TransactionIdMismatch(uint256 expectedTxId, uint256 providedTxId);
63
65
  error PendingSecureRequest();
64
66
 
@@ -72,23 +74,27 @@ library SharedValidation {
72
74
  error InvalidVValue(uint8 v);
73
75
  error ECDSAInvalidSignature(address recoveredSigner);
74
76
  error GasPriceExceedsMax(uint256 currentGasPrice, uint256 maxGasPrice);
77
+ error MetaTxRecordMismatchStoredTx(uint256 txId);
78
+ error MetaTxPaymentMismatchStoredTx(uint256 txId);
75
79
 
76
80
  // Consolidated resource errors
77
81
  error ResourceNotFound(bytes32 resourceId);
78
82
  error ResourceAlreadyExists(bytes32 resourceId);
79
83
  error CannotModifyProtected(bytes32 resourceId);
84
+ error GrantNotRevocable(bytes4 functionSelector);
80
85
 
81
86
  // Consolidated item errors (for addresses: wallets, policies, etc.)
82
87
  error ItemAlreadyExists(address item);
83
88
  error ItemNotFound(address item);
84
89
  error InvalidOperation(address item);
90
+ error DefinitionNotIDefinition(address definition);
85
91
 
86
92
  // Role and function errors with context
87
93
  error RoleWalletLimitReached(uint256 currentCount, uint256 maxWallets);
88
94
  error MaxWalletsZero(uint256 provided);
89
95
  error ConflictingMetaTxPermissions(bytes4 functionSelector);
90
96
  error InternalFunctionNotAccessible(bytes4 functionSelector);
91
- error ContractFunctionMustBeProtected(bytes4 functionSelector, string functionSignature);
97
+ error ContractFunctionMustBeProtected(bytes4 functionSelector);
92
98
  error TargetNotWhitelisted(address target, bytes4 functionSelector);
93
99
  error FunctionSelectorMismatch(bytes4 providedSelector, bytes4 derivedSelector);
94
100
  error HandlerForSelectorMismatch(bytes4 schemaHandlerForSelector, bytes4 permissionHandlerForSelector);
@@ -96,6 +102,7 @@ library SharedValidation {
96
102
  error OperationFailed();
97
103
 
98
104
  // Payment and balance errors with context
105
+ error InvalidPayment();
99
106
  error InsufficientBalance(uint256 currentBalance, uint256 requiredAmount);
100
107
  error PaymentFailed(address recipient, uint256 amount, bytes reason);
101
108
 
@@ -119,8 +126,28 @@ library SharedValidation {
119
126
  function validateNotZeroAddress(address addr) internal pure {
120
127
  if (addr == address(0)) revert InvalidAddress(addr);
121
128
  }
122
-
123
-
129
+
130
+ /**
131
+ * @dev Validates that payment details are empty (no attached payment).
132
+ * @param recipient The payment recipient address
133
+ * @param nativeTokenAmount The native token payment amount
134
+ * @param erc20TokenAddress The ERC20 token address
135
+ * @param erc20TokenAmount The ERC20 payment amount
136
+ */
137
+ function validateEmptyPayment(
138
+ address recipient,
139
+ uint256 nativeTokenAmount,
140
+ address erc20TokenAddress,
141
+ uint256 erc20TokenAmount
142
+ ) internal pure {
143
+ if (
144
+ recipient != address(0) ||
145
+ nativeTokenAmount != 0 ||
146
+ erc20TokenAddress != address(0) ||
147
+ erc20TokenAmount != 0
148
+ ) revert InvalidPayment();
149
+ }
150
+
124
151
  /**
125
152
  * @dev Validates that a new address is different from the current address
126
153
  * @param newAddress The proposed new address
@@ -158,6 +185,32 @@ library SharedValidation {
158
185
  function validateHandlerContract(address handler) internal pure {
159
186
  if (handler == address(0)) revert InvalidAddress(handler);
160
187
  }
188
+
189
+ /**
190
+ * @dev Validates that the signed handler selector matches the live wrapper entrypoint selector.
191
+ * IMPORTANT: pass the wrapper selector from wrapper context (`bytes4(msg.sig)` in the wrapper),
192
+ * not from external-library context.
193
+ * @param handlerSelector Selector embedded in signed MetaTxParams
194
+ * @param entrySelector Selector of the wrapper entrypoint executing the meta-tx
195
+ */
196
+ function validateMetaTxHandlerSelectorBinding(
197
+ bytes4 handlerSelector,
198
+ bytes4 entrySelector
199
+ ) internal pure {
200
+ if (handlerSelector != entrySelector) {
201
+ revert MetaTxHandlerSelectorMismatch(handlerSelector, entrySelector);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * @dev Validates that the signed handler contract matches the active verifying contract (`address(this)`).
207
+ * @param handlerContract Address embedded in signed MetaTxParams
208
+ */
209
+ function validateMetaTxHandlerContractBinding(address handlerContract) internal view {
210
+ if (handlerContract != address(this)) {
211
+ revert MetaTxHandlerContractMismatch(handlerContract, address(this));
212
+ }
213
+ }
161
214
 
162
215
  // ============ TIME AND DEADLINE VALIDATION FUNCTIONS ============
163
216
 
@@ -169,14 +222,6 @@ library SharedValidation {
169
222
  if (timeLockPeriod == 0) revert TimeLockPeriodZero(timeLockPeriod);
170
223
  }
171
224
 
172
- /**
173
- * @dev Validates that a deadline is in the future
174
- * @param deadline The deadline timestamp to validate
175
- */
176
- function validateDeadline(uint256 deadline) internal view {
177
- if (deadline <= block.timestamp) revert DeadlineInPast(deadline, block.timestamp);
178
- }
179
-
180
225
  /**
181
226
  * @dev Validates that a new time lock period is different from the current one
182
227
  * @param newPeriod The new time lock period
@@ -196,8 +241,9 @@ library SharedValidation {
196
241
  }
197
242
 
198
243
  /**
199
- * @dev Validates that a meta-transaction has not expired
200
- * @param deadline The deadline of the meta-transaction
244
+ * @dev Validates that a meta-transaction deadline has not passed (inclusive boundary: `block.timestamp == deadline` is valid).
245
+ * Used both when building unsigned meta-tx payloads (`EngineBlox.generateMetaTransaction`) and when verifying submitted meta-txs.
246
+ * @param deadline The deadline timestamp from `MetaTxParams`
201
247
  */
202
248
  function validateMetaTxDeadline(uint256 deadline) internal view {
203
249
  if (block.timestamp > deadline) revert MetaTxExpired(deadline, block.timestamp);
@@ -307,11 +353,12 @@ library SharedValidation {
307
353
  }
308
354
 
309
355
  /**
310
- * @dev Validates that a transaction exists (has non-zero ID)
356
+ * @dev Validates that `txId` refers to a minted record: non-zero and at most `txCounter` (inclusive).
311
357
  * @param txId The transaction ID to validate
358
+ * @param txCounter The engine's `txCounter` after the record was allocated (valid ids are `1..txCounter`)
312
359
  */
313
- function validateTransactionExists(uint256 txId) internal pure {
314
- if (txId == 0) revert ResourceNotFound(bytes32(uint256(txId)));
360
+ function validateTransactionExists(uint256 txId, uint256 txCounter) internal pure {
361
+ if (txId == 0 || txId > txCounter) revert ResourceNotFound(bytes32(uint256(txId)));
315
362
  }
316
363
 
317
364
  /**
@@ -402,12 +449,12 @@ library SharedValidation {
402
449
  // ============ UTILITY FUNCTIONS ============
403
450
 
404
451
  /**
405
- * @dev Validates that the first value is less than the second value
406
- * @param from The first value (should be less than 'to')
407
- * @param to The second value (should be greater than 'from')
452
+ * @dev Validates that the first value is not greater than the second (allows inclusive range: from <= to)
453
+ * @param from The first value (must be <= 'to' for a valid range)
454
+ * @param to The second value (must be >= 'from')
408
455
  */
409
456
  function validateLessThan(uint256 from, uint256 to) internal pure {
410
- if (from >= to) revert InvalidRange(from, to);
457
+ if (from > to) revert InvalidRange(from, to);
411
458
  }
412
459
 
413
460
  /**
@@ -0,0 +1,84 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ pragma solidity 0.8.35;
3
+
4
+ import "../execution/GuardController.sol";
5
+ import "../execution/interface/IGuardController.sol";
6
+ import "../access/RuntimeRBAC.sol";
7
+ import "../access/interface/IRuntimeRBAC.sol";
8
+ import "../security/SecureOwnable.sol";
9
+ import "../security/interface/ISecureOwnable.sol";
10
+ import "../lib/utils/SharedValidation.sol";
11
+
12
+ /**
13
+ * @title Account
14
+ * @dev Abstract account pattern combining GuardController, RuntimeRBAC, and SecureOwnable.
15
+ *
16
+ * Use this as the base for account-style contracts (e.g. AccountBlox) to avoid duplicating
17
+ * initialization, interface support, and receive/fallback boilerplate.
18
+ *
19
+ * Combines:
20
+ * - GuardController: Execution workflows and time-locked transactions
21
+ * - RuntimeRBAC: Runtime role creation and management
22
+ * - SecureOwnable: Secure ownership transfer and management
23
+ *
24
+ * @custom:security-contact security@particlecs.com
25
+ */
26
+ abstract contract Account is GuardController, RuntimeRBAC, SecureOwnable {
27
+ /**
28
+ * @dev Emitted when plain ETH is received (receive()).
29
+ * @param sender Address that sent the ETH
30
+ * @param value Amount of wei received
31
+ * @custom:security Gas-efficient so receive() stays within 2,300 gas stipend (transfer/send compatible).
32
+ */
33
+ event EthReceived(address indexed sender, uint256 value);
34
+
35
+ /**
36
+ * @notice Initializer for the Account pattern (GuardController + RuntimeRBAC + SecureOwnable).
37
+ * @param initialOwner The initial owner address
38
+ * @param broadcaster The broadcaster address
39
+ * @param recovery The recovery address
40
+ * @param timeLockPeriodSec The timelock period in seconds
41
+ * @param eventForwarder The event forwarder address (optional)
42
+ */
43
+ function initialize(
44
+ address initialOwner,
45
+ address broadcaster,
46
+ address recovery,
47
+ uint256 timeLockPeriodSec,
48
+ address eventForwarder
49
+ ) public virtual override(GuardController, RuntimeRBAC, SecureOwnable) onlyInitializing {
50
+ GuardController.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
51
+ RuntimeRBAC.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
52
+ SecureOwnable.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
53
+ }
54
+
55
+ /**
56
+ * @dev See {IERC165-supportsInterface}.
57
+ * @notice GuardController, RuntimeRBAC, and SecureOwnable each extend BaseStateMachine directly; a single
58
+ * `super` chain only walks one branch. We OR the three component interface IDs here, then delegate
59
+ * once to `super` for IBaseStateMachine / ERC165 — avoids tripling BaseStateMachine+ERC165 work.
60
+ */
61
+ function supportsInterface(bytes4 interfaceId) public view virtual override(GuardController, RuntimeRBAC, SecureOwnable) returns (bool) {
62
+ return interfaceId == type(IGuardController).interfaceId
63
+ || interfaceId == type(IRuntimeRBAC).interfaceId
64
+ || interfaceId == type(ISecureOwnable).interfaceId
65
+ || super.supportsInterface(interfaceId);
66
+ }
67
+
68
+ /**
69
+ * @dev Accepts plain ETH transfers (no calldata).
70
+ * @notice General-use wallet: ETH can be sent naturally; balance is credited.
71
+ * @custom:security No external calls—reentrancy-safe; outgoing ETH only via GuardController execution. Uses simple emit to stay within 2,300 gas stipend (transfer/send compatible).
72
+ */
73
+ receive() external payable virtual {
74
+ emit EthReceived(msg.sender, msg.value);
75
+ }
76
+
77
+ /**
78
+ * @dev Rejects calls with unknown selector (with or without value).
79
+ * @notice Only plain transfers hit receive(); all other calls revert.
80
+ */
81
+ fallback() external payable virtual {
82
+ revert SharedValidation.NotSupported();
83
+ }
84
+ }