@bloxchain/contracts 1.0.0-alpha
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 +49 -0
- package/abi/BareBlox.abi.json +1341 -0
- package/abi/BaseStateMachine.abi.json +1308 -0
- package/abi/ControlBlox.abi.json +6210 -0
- package/abi/EngineBlox.abi.json +872 -0
- package/abi/GuardController.abi.json +3045 -0
- package/abi/IDefinition.abi.json +94 -0
- package/abi/RoleBlox.abi.json +4569 -0
- package/abi/RuntimeRBAC.abi.json +1857 -0
- package/abi/RuntimeRBACDefinitions.abi.json +133 -0
- package/abi/SecureBlox.abi.json +4085 -0
- package/abi/SecureOwnable.abi.json +4085 -0
- package/abi/SecureOwnableDefinitions.abi.json +354 -0
- package/abi/SimpleRWA20.abi.json +5545 -0
- package/abi/SimpleRWA20Definitions.abi.json +172 -0
- package/abi/SimpleVault.abi.json +5208 -0
- package/abi/SimpleVaultDefinitions.abi.json +250 -0
- package/contracts/core/access/RuntimeRBAC.sol +344 -0
- package/contracts/core/access/interface/IRuntimeRBAC.sol +108 -0
- package/contracts/core/access/lib/definitions/RuntimeRBACDefinitions.sol +168 -0
- package/contracts/core/base/BaseStateMachine.sol +834 -0
- package/contracts/core/base/interface/IBaseStateMachine.sol +153 -0
- package/contracts/core/execution/GuardController.sol +507 -0
- package/contracts/core/execution/interface/IGuardController.sol +120 -0
- package/contracts/core/execution/lib/definitions/GuardControllerDefinitions.sol +401 -0
- package/contracts/core/lib/EngineBlox.sol +2283 -0
- package/contracts/core/security/SecureOwnable.sol +419 -0
- package/contracts/core/security/interface/ISecureOwnable.sol +118 -0
- package/contracts/core/security/lib/definitions/SecureOwnableDefinitions.sol +757 -0
- package/contracts/interfaces/IDefinition.sol +40 -0
- package/contracts/interfaces/IEventForwarder.sol +33 -0
- package/contracts/interfaces/IOnActionHook.sol +79 -0
- package/contracts/utils/SharedValidation.sol +486 -0
- package/package.json +47 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.33;
|
|
3
|
+
|
|
4
|
+
import "../core/lib/EngineBlox.sol";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @dev Interface for definition contracts that provide operation types, function schemas, and role permissions
|
|
8
|
+
*
|
|
9
|
+
* This interface allows contracts to dynamically load their configuration from external
|
|
10
|
+
* definition contracts, enabling modular and extensible contract initialization.
|
|
11
|
+
*
|
|
12
|
+
* Definition contracts should implement this interface to provide:
|
|
13
|
+
* - Operation type definitions (what operations are supported)
|
|
14
|
+
* - Function schema definitions (how functions are structured)
|
|
15
|
+
* - Role permission definitions (who can do what)
|
|
16
|
+
*/
|
|
17
|
+
interface IDefinition {
|
|
18
|
+
/**
|
|
19
|
+
* @dev Struct to hold role permission data
|
|
20
|
+
* @param roleHashes Array of role hashes
|
|
21
|
+
* @param functionPermissions Array of function permissions (parallel to roleHashes)
|
|
22
|
+
*/
|
|
23
|
+
struct RolePermission {
|
|
24
|
+
bytes32[] roleHashes;
|
|
25
|
+
EngineBlox.FunctionPermission[] functionPermissions;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @dev Returns all function schema definitions
|
|
30
|
+
* @return Array of function schema definitions
|
|
31
|
+
*/
|
|
32
|
+
function getFunctionSchemas() external pure returns (EngineBlox.FunctionSchema[] memory);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @dev Returns all role hashes and their corresponding function permissions
|
|
36
|
+
* @return RolePermission struct containing roleHashes and functionPermissions arrays
|
|
37
|
+
*/
|
|
38
|
+
function getRolePermissions() external pure returns (RolePermission memory);
|
|
39
|
+
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.33;
|
|
3
|
+
|
|
4
|
+
// Import TxRecord struct from EngineBlox
|
|
5
|
+
import "../core/lib/EngineBlox.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title IEventForwarder
|
|
9
|
+
* @dev Interface for the event forwarder contract
|
|
10
|
+
*
|
|
11
|
+
* This interface defines the contract for forwarding events from deployed instances
|
|
12
|
+
* to a centralized event monitoring system. It uses function selectors for efficient
|
|
13
|
+
* event identification and categorization.
|
|
14
|
+
*/
|
|
15
|
+
interface IEventForwarder {
|
|
16
|
+
/**
|
|
17
|
+
* @dev Forward a transaction event from a deployed instance
|
|
18
|
+
* @param txId The transaction ID
|
|
19
|
+
* @param functionSelector The function selector for the event (bytes4)
|
|
20
|
+
* @param status The transaction status
|
|
21
|
+
* @param requester The address of the requester
|
|
22
|
+
* @param target The target contract address
|
|
23
|
+
* @param operationType The type of operation
|
|
24
|
+
*/
|
|
25
|
+
function forwardTxEvent(
|
|
26
|
+
uint256 txId,
|
|
27
|
+
bytes4 functionSelector,
|
|
28
|
+
EngineBlox.TxStatus status,
|
|
29
|
+
address requester,
|
|
30
|
+
address target,
|
|
31
|
+
bytes32 operationType
|
|
32
|
+
) external;
|
|
33
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.33;
|
|
3
|
+
|
|
4
|
+
import "../core/lib/EngineBlox.sol";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @title IOnActionHook
|
|
8
|
+
* @dev Minimal interface for external hook contracts attached to state machine actions
|
|
9
|
+
*
|
|
10
|
+
* @notice This interface is intentionally small to keep overall contract size low.
|
|
11
|
+
* @notice Implementations can choose which functions to support; unneeded ones can revert.
|
|
12
|
+
*/
|
|
13
|
+
interface IOnActionHook {
|
|
14
|
+
/**
|
|
15
|
+
* @dev Called after a transaction request is created
|
|
16
|
+
* @param txRecord The created transaction record
|
|
17
|
+
* @param caller The address that initiated the request
|
|
18
|
+
*/
|
|
19
|
+
function onRequest(
|
|
20
|
+
EngineBlox.TxRecord memory txRecord,
|
|
21
|
+
address caller
|
|
22
|
+
) external;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @dev Called after a pending transaction is approved (time-lock flow)
|
|
26
|
+
* @param txRecord The updated transaction record
|
|
27
|
+
* @param caller The address that approved the transaction
|
|
28
|
+
*/
|
|
29
|
+
function onApprove(
|
|
30
|
+
EngineBlox.TxRecord memory txRecord,
|
|
31
|
+
address caller
|
|
32
|
+
) external;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @dev Called after a pending transaction is cancelled
|
|
36
|
+
* @param txRecord The updated transaction record
|
|
37
|
+
* @param caller The address that cancelled the transaction
|
|
38
|
+
*/
|
|
39
|
+
function onCancel(
|
|
40
|
+
EngineBlox.TxRecord memory txRecord,
|
|
41
|
+
address caller
|
|
42
|
+
) external;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @dev Called after a transaction is approved via meta-transaction
|
|
46
|
+
* @param txRecord The updated transaction record
|
|
47
|
+
* @param metaTx The meta-transaction used for approval
|
|
48
|
+
* @param caller The address executing the meta-transaction
|
|
49
|
+
*/
|
|
50
|
+
function onMetaApprove(
|
|
51
|
+
EngineBlox.TxRecord memory txRecord,
|
|
52
|
+
EngineBlox.MetaTransaction memory metaTx,
|
|
53
|
+
address caller
|
|
54
|
+
) external;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @dev Called after a transaction is cancelled via meta-transaction
|
|
58
|
+
* @param txRecord The updated transaction record
|
|
59
|
+
* @param metaTx The meta-transaction used for cancellation
|
|
60
|
+
* @param caller The address executing the meta-transaction
|
|
61
|
+
*/
|
|
62
|
+
function onMetaCancel(
|
|
63
|
+
EngineBlox.TxRecord memory txRecord,
|
|
64
|
+
EngineBlox.MetaTransaction memory metaTx,
|
|
65
|
+
address caller
|
|
66
|
+
) external;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @dev Called after a transaction is requested and approved in one step via meta-transaction
|
|
70
|
+
* @param txRecord The created + approved transaction record
|
|
71
|
+
* @param metaTx The meta-transaction used for the operation
|
|
72
|
+
* @param caller The address executing the meta-transaction
|
|
73
|
+
*/
|
|
74
|
+
function onRequestAndApprove(
|
|
75
|
+
EngineBlox.TxRecord memory txRecord,
|
|
76
|
+
EngineBlox.MetaTransaction memory metaTx,
|
|
77
|
+
address caller
|
|
78
|
+
) external;
|
|
79
|
+
}
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.33;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title SharedValidation
|
|
6
|
+
* @dev Optimized shared library containing common validation functions using enhanced custom errors
|
|
7
|
+
*
|
|
8
|
+
* This library is designed to reduce contract size by centralizing common validation logic
|
|
9
|
+
* and using gas-efficient custom errors instead of string constants. This approach provides
|
|
10
|
+
* significant gas savings and contract size reduction while maintaining clear error context.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Enhanced custom errors with contextual parameters
|
|
14
|
+
* - Address validation functions
|
|
15
|
+
* - Time and deadline validation
|
|
16
|
+
* - Signature validation utilities
|
|
17
|
+
* - Permission and authorization checks
|
|
18
|
+
* - Operation type validation
|
|
19
|
+
* - Gas and transaction validation
|
|
20
|
+
*
|
|
21
|
+
* This library follows the security rules defined in .cursorrules and implements
|
|
22
|
+
* the Checks-Effects-Interactions pattern where applicable.
|
|
23
|
+
*
|
|
24
|
+
* Gas Optimization Benefits:
|
|
25
|
+
* - ~50% gas reduction compared to string-based errors
|
|
26
|
+
* - Significant contract size reduction
|
|
27
|
+
* - Enhanced error context with parameters
|
|
28
|
+
* - Modern Solidity best practices (0.8.4+)
|
|
29
|
+
*/
|
|
30
|
+
library SharedValidation {
|
|
31
|
+
|
|
32
|
+
// ============ ENHANCED CUSTOM ERRORS ============
|
|
33
|
+
|
|
34
|
+
// Address validation errors with context
|
|
35
|
+
error InvalidAddress(address provided);
|
|
36
|
+
error NotNewAddress(address newAddress, address currentAddress);
|
|
37
|
+
|
|
38
|
+
// Time and deadline errors with context
|
|
39
|
+
error InvalidTimeLockPeriod(uint256 provided);
|
|
40
|
+
error TimeLockPeriodZero(uint256 provided);
|
|
41
|
+
error DeadlineInPast(uint256 deadline, uint256 currentTime);
|
|
42
|
+
error MetaTxExpired(uint256 deadline, uint256 currentTime);
|
|
43
|
+
error BeforeReleaseTime(uint256 releaseTime, uint256 currentTime);
|
|
44
|
+
error NewTimelockSame(uint256 newPeriod, uint256 currentPeriod);
|
|
45
|
+
|
|
46
|
+
// Permission and authorization errors with context
|
|
47
|
+
error NoPermission(address caller);
|
|
48
|
+
error NoPermissionForFunction(address caller, bytes4 functionSelector);
|
|
49
|
+
error RestrictedOwner(address caller, address owner);
|
|
50
|
+
error RestrictedOwnerRecovery(address caller, address owner, address recovery);
|
|
51
|
+
error RestrictedRecovery(address caller, address recovery);
|
|
52
|
+
error RestrictedBroadcaster(address caller, address broadcaster);
|
|
53
|
+
error SignerNotAuthorized(address signer);
|
|
54
|
+
error OnlyCallableByContract(address caller, address contractAddress);
|
|
55
|
+
|
|
56
|
+
// Transaction and operation errors with context
|
|
57
|
+
error NotSupported();
|
|
58
|
+
error InvalidOperationType(bytes32 actualType, bytes32 expectedType);
|
|
59
|
+
error ZeroOperationTypeNotAllowed();
|
|
60
|
+
error TransactionStatusMismatch(uint8 expectedStatus, uint8 currentStatus);
|
|
61
|
+
error AlreadyInitialized();
|
|
62
|
+
error TransactionIdMismatch(uint256 expectedTxId, uint256 providedTxId);
|
|
63
|
+
|
|
64
|
+
// Signature and meta-transaction errors with context
|
|
65
|
+
error InvalidSignatureLength(uint256 providedLength, uint256 expectedLength);
|
|
66
|
+
error InvalidSignature(bytes signature);
|
|
67
|
+
error InvalidNonce(uint256 providedNonce, uint256 expectedNonce);
|
|
68
|
+
error ChainIdMismatch(uint256 providedChainId, uint256 expectedChainId);
|
|
69
|
+
error InvalidHandlerSelector(bytes4 selector);
|
|
70
|
+
error InvalidSValue(bytes32 s);
|
|
71
|
+
error InvalidVValue(uint8 v);
|
|
72
|
+
error ECDSAInvalidSignature(address recoveredSigner);
|
|
73
|
+
error GasPriceExceedsMax(uint256 currentGasPrice, uint256 maxGasPrice);
|
|
74
|
+
|
|
75
|
+
// Consolidated resource errors
|
|
76
|
+
error ResourceNotFound(bytes32 resourceId);
|
|
77
|
+
error ResourceAlreadyExists(bytes32 resourceId);
|
|
78
|
+
error CannotModifyProtected(bytes32 resourceId);
|
|
79
|
+
|
|
80
|
+
// Consolidated item errors (for addresses: wallets, policies, etc.)
|
|
81
|
+
error ItemAlreadyExists(address item);
|
|
82
|
+
error ItemNotFound(address item);
|
|
83
|
+
error InvalidOperation(address item);
|
|
84
|
+
|
|
85
|
+
// Role and function errors with context
|
|
86
|
+
error RoleWalletLimitReached(uint256 currentCount, uint256 maxWallets);
|
|
87
|
+
error MaxWalletsZero(uint256 provided);
|
|
88
|
+
error ConflictingMetaTxPermissions(bytes4 functionSelector);
|
|
89
|
+
error InternalFunctionNotAccessible(bytes4 functionSelector);
|
|
90
|
+
error ContractFunctionMustBeProtected(bytes4 functionSelector, string functionSignature);
|
|
91
|
+
error TargetNotWhitelisted(address target, bytes4 functionSelector);
|
|
92
|
+
error FunctionSelectorMismatch(bytes4 providedSelector, bytes4 derivedSelector);
|
|
93
|
+
error HandlerForSelectorMismatch(bytes4 schemaHandlerForSelector, bytes4 permissionHandlerForSelector);
|
|
94
|
+
error InvalidRange(uint256 from, uint256 to);
|
|
95
|
+
error OperationFailed();
|
|
96
|
+
|
|
97
|
+
// Payment and balance errors with context
|
|
98
|
+
error InsufficientBalance(uint256 currentBalance, uint256 requiredAmount);
|
|
99
|
+
error PaymentFailed(address recipient, uint256 amount, bytes reason);
|
|
100
|
+
|
|
101
|
+
// Array validation errors with context
|
|
102
|
+
error ArrayLengthMismatch(uint256 array1Length, uint256 array2Length);
|
|
103
|
+
error IndexOutOfBounds(uint256 index, uint256 arrayLength);
|
|
104
|
+
|
|
105
|
+
// System limit errors
|
|
106
|
+
error BatchSizeExceeded(uint256 currentSize, uint256 maxSize);
|
|
107
|
+
error MaxRolesExceeded(uint256 currentCount, uint256 maxRoles);
|
|
108
|
+
error MaxHooksExceeded(uint256 currentCount, uint256 maxHooks);
|
|
109
|
+
error MaxFunctionsExceeded(uint256 currentCount, uint256 maxFunctions);
|
|
110
|
+
error RangeSizeExceeded(uint256 rangeSize, uint256 maxRangeSize);
|
|
111
|
+
|
|
112
|
+
// ============ ADDRESS VALIDATION FUNCTIONS ============
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @dev Validates that an address is not the zero address
|
|
116
|
+
* @param addr The address to validate
|
|
117
|
+
*/
|
|
118
|
+
function validateNotZeroAddress(address addr) internal pure {
|
|
119
|
+
if (addr == address(0)) revert InvalidAddress(addr);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @dev Validates that a new address is different from the current address
|
|
125
|
+
* @param newAddress The proposed new address
|
|
126
|
+
* @param currentAddress The current address to compare against
|
|
127
|
+
*/
|
|
128
|
+
function validateNewAddress(address newAddress, address currentAddress) internal pure {
|
|
129
|
+
if (newAddress == currentAddress) revert NotNewAddress(newAddress, currentAddress);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @dev Validates that an address is not the zero address and is different from current
|
|
134
|
+
* @param newAddress The proposed new address
|
|
135
|
+
* @param currentAddress The current address to compare against
|
|
136
|
+
*/
|
|
137
|
+
function validateAddressUpdate(
|
|
138
|
+
address newAddress,
|
|
139
|
+
address currentAddress
|
|
140
|
+
) internal pure {
|
|
141
|
+
validateNotZeroAddress(newAddress);
|
|
142
|
+
validateNewAddress(newAddress, currentAddress);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @dev Validates that a target address is not zero
|
|
147
|
+
* @param target The target address to validate
|
|
148
|
+
*/
|
|
149
|
+
function validateTargetAddress(address target) internal pure {
|
|
150
|
+
if (target == address(0)) revert InvalidAddress(target);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @dev Validates that a handler contract address is not zero
|
|
155
|
+
* @param handler The handler contract address to validate
|
|
156
|
+
*/
|
|
157
|
+
function validateHandlerContract(address handler) internal pure {
|
|
158
|
+
if (handler == address(0)) revert InvalidAddress(handler);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============ TIME AND DEADLINE VALIDATION FUNCTIONS ============
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @dev Validates that a time lock period is greater than zero
|
|
165
|
+
* @param timeLockPeriod The time lock period to validate
|
|
166
|
+
*/
|
|
167
|
+
function validateTimeLockPeriod(uint256 timeLockPeriod) internal pure {
|
|
168
|
+
if (timeLockPeriod == 0) revert TimeLockPeriodZero(timeLockPeriod);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @dev Validates that a deadline is in the future
|
|
173
|
+
* @param deadline The deadline timestamp to validate
|
|
174
|
+
*/
|
|
175
|
+
function validateDeadline(uint256 deadline) internal view {
|
|
176
|
+
if (deadline <= block.timestamp) revert DeadlineInPast(deadline, block.timestamp);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @dev Validates that a new time lock period is different from the current one
|
|
181
|
+
* @param newPeriod The new time lock period
|
|
182
|
+
* @param currentPeriod The current time lock period
|
|
183
|
+
*/
|
|
184
|
+
function validateTimeLockUpdate(uint256 newPeriod, uint256 currentPeriod) internal pure {
|
|
185
|
+
validateTimeLockPeriod(newPeriod);
|
|
186
|
+
if (newPeriod == currentPeriod) revert NewTimelockSame(newPeriod, currentPeriod);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @dev Validates that the current time is after the release time
|
|
191
|
+
* @param releaseTime The release time to check against
|
|
192
|
+
*/
|
|
193
|
+
function validateReleaseTime(uint256 releaseTime) internal view {
|
|
194
|
+
if (block.timestamp < releaseTime) revert BeforeReleaseTime(releaseTime, block.timestamp);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @dev Validates that a meta-transaction has not expired
|
|
199
|
+
* @param deadline The deadline of the meta-transaction
|
|
200
|
+
*/
|
|
201
|
+
function validateMetaTxDeadline(uint256 deadline) internal view {
|
|
202
|
+
if (block.timestamp > deadline) revert MetaTxExpired(deadline, block.timestamp);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ============ SIGNATURE VALIDATION FUNCTIONS ============
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @dev Validates that a signature has the correct length (65 bytes)
|
|
209
|
+
* @param signature The signature to validate
|
|
210
|
+
*/
|
|
211
|
+
function validateSignatureLength(bytes memory signature) internal pure {
|
|
212
|
+
if (signature.length != 65) revert InvalidSignatureLength(signature.length, 65);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @dev Validates ECDSA signature parameters
|
|
217
|
+
* @param s The s parameter of the signature
|
|
218
|
+
* @param v The v parameter of the signature
|
|
219
|
+
*/
|
|
220
|
+
function validateSignatureParams(bytes32 s, uint8 v) internal pure {
|
|
221
|
+
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
|
|
222
|
+
revert InvalidSValue(s);
|
|
223
|
+
}
|
|
224
|
+
if (v != 27 && v != 28) revert InvalidVValue(v);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @dev Validates that a recovered signer is not the zero address
|
|
229
|
+
* @param signer The recovered signer address
|
|
230
|
+
*/
|
|
231
|
+
function validateRecoveredSigner(address signer) internal pure {
|
|
232
|
+
if (signer == address(0)) revert ECDSAInvalidSignature(signer);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ============ PERMISSION AND AUTHORIZATION FUNCTIONS ============
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @dev Validates that the caller is the owner
|
|
239
|
+
* @param owner The current owner address
|
|
240
|
+
*/
|
|
241
|
+
function validateOwner(address owner) internal view {
|
|
242
|
+
if (owner != msg.sender) revert RestrictedOwner(msg.sender, owner);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @dev Validates that the caller is either the owner or recovery
|
|
247
|
+
* @param owner The current owner address
|
|
248
|
+
* @param recovery The current recovery address
|
|
249
|
+
*/
|
|
250
|
+
function validateOwnerOrRecovery(address owner, address recovery) internal view {
|
|
251
|
+
if (msg.sender != owner && msg.sender != recovery) {
|
|
252
|
+
revert RestrictedOwnerRecovery(msg.sender, owner, recovery);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* @dev Validates that the caller is the recovery address
|
|
258
|
+
* @param recovery The current recovery address
|
|
259
|
+
*/
|
|
260
|
+
function validateRecovery(address recovery) internal view {
|
|
261
|
+
if (msg.sender != recovery) revert RestrictedRecovery(msg.sender, recovery);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @dev Validates that the caller is the broadcaster
|
|
266
|
+
* @param broadcaster The current broadcaster address
|
|
267
|
+
*/
|
|
268
|
+
function validateBroadcaster(address broadcaster) internal view {
|
|
269
|
+
if (msg.sender != broadcaster) revert RestrictedBroadcaster(msg.sender, broadcaster);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @dev Validates that the signer of a meta-transaction is the owner
|
|
274
|
+
* @param signer The signer address from the meta-transaction
|
|
275
|
+
* @param owner The current owner address
|
|
276
|
+
*/
|
|
277
|
+
function validateOwnerIsSigner(address signer, address owner) internal pure {
|
|
278
|
+
if (signer != owner) revert NoPermission(signer);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @dev Validates that the function is being called internally by the contract itself
|
|
283
|
+
* @param contractAddress The address of the contract
|
|
284
|
+
*/
|
|
285
|
+
function validateInternalCall(address contractAddress) internal view {
|
|
286
|
+
if (msg.sender != contractAddress) revert OnlyCallableByContract(msg.sender, contractAddress);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ============ TRANSACTION AND OPERATION VALIDATION FUNCTIONS ============
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @dev Validates that an operation type is not zero
|
|
293
|
+
* @param operationType The operation type to validate
|
|
294
|
+
*/
|
|
295
|
+
function validateOperationTypeNotZero(bytes32 operationType) internal pure {
|
|
296
|
+
if (operationType == bytes32(0)) revert ZeroOperationTypeNotAllowed();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @dev Validates that an operation type matches the expected type
|
|
301
|
+
* @param actualType The actual operation type
|
|
302
|
+
* @param expectedType The expected operation type
|
|
303
|
+
*/
|
|
304
|
+
function validateOperationType(bytes32 actualType, bytes32 expectedType) internal pure {
|
|
305
|
+
if (actualType != expectedType) revert InvalidOperationType(actualType, expectedType);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @dev Validates that a transaction exists (has non-zero ID)
|
|
310
|
+
* @param txId The transaction ID to validate
|
|
311
|
+
*/
|
|
312
|
+
function validateTransactionExists(uint256 txId) internal pure {
|
|
313
|
+
if (txId == 0) revert ResourceNotFound(bytes32(uint256(txId)));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* @dev Validates that a transaction ID matches the expected value
|
|
318
|
+
* @param txId The transaction ID to validate
|
|
319
|
+
* @param expectedTxId The expected transaction ID
|
|
320
|
+
*/
|
|
321
|
+
function validateTransactionId(uint256 txId, uint256 expectedTxId) internal pure {
|
|
322
|
+
if (txId != expectedTxId) revert TransactionIdMismatch(expectedTxId, txId);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ============ META-TRANSACTION VALIDATION FUNCTIONS ============
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @dev Validates chain ID matches the current chain
|
|
329
|
+
* @param chainId The chain ID to validate
|
|
330
|
+
*/
|
|
331
|
+
function validateChainId(uint256 chainId) internal view {
|
|
332
|
+
if (chainId != block.chainid) revert ChainIdMismatch(chainId, block.chainid);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* @dev Validates that a handler selector is not zero
|
|
337
|
+
* @param selector The handler selector to validate
|
|
338
|
+
*/
|
|
339
|
+
function validateHandlerSelector(bytes4 selector) internal pure {
|
|
340
|
+
if (selector == bytes4(0)) revert InvalidHandlerSelector(selector);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* @dev Validates that a handler selector matches the expected selector
|
|
345
|
+
* @param actualSelector The actual handler selector from the meta transaction
|
|
346
|
+
* @param expectedSelector The expected handler selector to validate against
|
|
347
|
+
*/
|
|
348
|
+
function validateHandlerSelectorMatch(bytes4 actualSelector, bytes4 expectedSelector) internal pure {
|
|
349
|
+
if (actualSelector != expectedSelector) revert InvalidHandlerSelector(actualSelector);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* @dev Validates that a nonce matches the expected value
|
|
354
|
+
* @param nonce The nonce to validate
|
|
355
|
+
* @param expectedNonce The expected nonce value
|
|
356
|
+
*/
|
|
357
|
+
function validateNonce(uint256 nonce, uint256 expectedNonce) internal pure {
|
|
358
|
+
if (nonce != expectedNonce) revert InvalidNonce(nonce, expectedNonce);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @dev Validates that the current transaction's gas price is within limits
|
|
363
|
+
* @param maxGasPrice The maximum allowed gas price (in wei)
|
|
364
|
+
*/
|
|
365
|
+
function validateGasPrice(uint256 maxGasPrice) internal view {
|
|
366
|
+
if (maxGasPrice == 0) return; // No limit set
|
|
367
|
+
|
|
368
|
+
uint256 currentGasPrice = tx.gasprice;
|
|
369
|
+
if (currentGasPrice > maxGasPrice) {
|
|
370
|
+
revert GasPriceExceedsMax(currentGasPrice, maxGasPrice);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ============ ROLE AND FUNCTION VALIDATION FUNCTIONS ============
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @dev Validates that a role hasn't reached its wallet limit
|
|
378
|
+
* @param currentCount The current number of wallets in the role
|
|
379
|
+
* @param maxWallets The maximum number of wallets allowed
|
|
380
|
+
*/
|
|
381
|
+
function validateWalletLimit(uint256 currentCount, uint256 maxWallets) internal pure {
|
|
382
|
+
if (currentCount >= maxWallets) revert RoleWalletLimitReached(currentCount, maxWallets);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* @dev Validates that max wallets is greater than zero
|
|
387
|
+
* @param maxWallets The maximum number of wallets
|
|
388
|
+
*/
|
|
389
|
+
function validateMaxWalletsGreaterThanZero(uint256 maxWallets) internal pure {
|
|
390
|
+
if (maxWallets == 0) revert MaxWalletsZero(maxWallets);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* @dev Validates that a role name is not empty
|
|
395
|
+
* @param roleName The role name to validate
|
|
396
|
+
*/
|
|
397
|
+
function validateRoleNameNotEmpty(string memory roleName) internal pure {
|
|
398
|
+
if (bytes(roleName).length == 0) revert ResourceNotFound(keccak256(bytes(roleName)));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// ============ UTILITY FUNCTIONS ============
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @dev Validates that the first value is less than the second value
|
|
405
|
+
* @param from The first value (should be less than 'to')
|
|
406
|
+
* @param to The second value (should be greater than 'from')
|
|
407
|
+
*/
|
|
408
|
+
function validateLessThan(uint256 from, uint256 to) internal pure {
|
|
409
|
+
if (from >= to) revert InvalidRange(from, to);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* @dev Validates that two arrays have the same length
|
|
414
|
+
* @param array1Length The length of the first array
|
|
415
|
+
* @param array2Length The length of the second array
|
|
416
|
+
*/
|
|
417
|
+
function validateArrayLengthMatch(uint256 array1Length, uint256 array2Length) internal pure {
|
|
418
|
+
if (array1Length != array2Length) revert ArrayLengthMismatch(array1Length, array2Length);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ============ SYSTEM LIMIT VALIDATION FUNCTIONS ============
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* @dev Validates that batch size doesn't exceed limit
|
|
425
|
+
* @param batchSize The current batch size
|
|
426
|
+
* @param maxBatchSize The maximum allowed batch size (0 = unlimited)
|
|
427
|
+
*/
|
|
428
|
+
function validateBatchSize(uint256 batchSize, uint256 maxBatchSize) internal pure {
|
|
429
|
+
if (maxBatchSize > 0 && batchSize > maxBatchSize) {
|
|
430
|
+
revert BatchSizeExceeded(batchSize, maxBatchSize);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* @dev Validates that role count doesn't exceed limit
|
|
436
|
+
* @param currentCount The current role count
|
|
437
|
+
* @param maxRoles The maximum allowed roles (0 = unlimited)
|
|
438
|
+
*/
|
|
439
|
+
function validateRoleCount(uint256 currentCount, uint256 maxRoles) internal pure {
|
|
440
|
+
if (maxRoles > 0 && currentCount >= maxRoles) {
|
|
441
|
+
revert MaxRolesExceeded(currentCount, maxRoles);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* @dev Validates that hook count doesn't exceed limit
|
|
447
|
+
* @param currentCount The current hook count
|
|
448
|
+
* @param maxHooks The maximum allowed hooks (0 = unlimited)
|
|
449
|
+
*/
|
|
450
|
+
function validateHookCount(uint256 currentCount, uint256 maxHooks) internal pure {
|
|
451
|
+
if (maxHooks > 0 && currentCount >= maxHooks) {
|
|
452
|
+
revert MaxHooksExceeded(currentCount, maxHooks);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* @dev Validates that function count doesn't exceed limit
|
|
458
|
+
* @param currentCount The current function count
|
|
459
|
+
* @param maxFunctions The maximum allowed functions (0 = unlimited)
|
|
460
|
+
*/
|
|
461
|
+
function validateFunctionCount(uint256 currentCount, uint256 maxFunctions) internal pure {
|
|
462
|
+
if (maxFunctions > 0 && currentCount >= maxFunctions) {
|
|
463
|
+
revert MaxFunctionsExceeded(currentCount, maxFunctions);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @dev Validates that range size doesn't exceed limit
|
|
469
|
+
* @param rangeSize The range size
|
|
470
|
+
* @param maxRangeSize The maximum allowed range size (0 = unlimited)
|
|
471
|
+
*/
|
|
472
|
+
function validateRangeSize(uint256 rangeSize, uint256 maxRangeSize) internal pure {
|
|
473
|
+
if (maxRangeSize > 0 && rangeSize > maxRangeSize) {
|
|
474
|
+
revert RangeSizeExceeded(rangeSize, maxRangeSize);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* @dev Validates that an index is within bounds of an array
|
|
480
|
+
* @param index The index to validate
|
|
481
|
+
* @param arrayLength The length of the array
|
|
482
|
+
*/
|
|
483
|
+
function validateIndexInBounds(uint256 index, uint256 arrayLength) internal pure {
|
|
484
|
+
if (index >= arrayLength) revert IndexOutOfBounds(index, arrayLength);
|
|
485
|
+
}
|
|
486
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bloxchain/contracts",
|
|
3
|
+
"version": "1.0.0-alpha",
|
|
4
|
+
"description": "Library engine for building enterprise grade decentralized permissioned applications",
|
|
5
|
+
"files": [
|
|
6
|
+
"contracts",
|
|
7
|
+
"abi",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"prepublishOnly": "node scripts/prepublish-contracts.cjs",
|
|
12
|
+
"postpublish": "node scripts/postpublish-contracts.cjs"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"bloxchain",
|
|
16
|
+
"solidity",
|
|
17
|
+
"ethereum",
|
|
18
|
+
"smart-contracts",
|
|
19
|
+
"state-abstraction",
|
|
20
|
+
"security",
|
|
21
|
+
"multi-signature",
|
|
22
|
+
"rbac",
|
|
23
|
+
"secure-ownership"
|
|
24
|
+
],
|
|
25
|
+
"author": "Particle Crypto Security",
|
|
26
|
+
"license": "MPL-2.0",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/PracticalParticle/Bloxchain-Protocol.git",
|
|
30
|
+
"directory": "package"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://bloxchain.app/",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/PracticalParticle/Bloxchain-Protocol/issues",
|
|
35
|
+
"email": "security@particlecs.com"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@openzeppelin/contracts": "^5.4.0",
|
|
42
|
+
"@openzeppelin/contracts-upgradeable": "^5.4.0"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18.0.0"
|
|
46
|
+
}
|
|
47
|
+
}
|