@bloxchain/contracts 1.0.0-alpha.2 → 1.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/abi/BaseStateMachine.abi.json +85 -45
- package/abi/EngineBlox.abi.json +73 -90
- package/abi/GuardController.abi.json +252 -806
- package/abi/{SimpleVaultDefinitions.abi.json → GuardControllerDefinitions.abi.json} +170 -28
- package/abi/IDefinition.abi.json +5 -0
- package/abi/RuntimeRBAC.abi.json +155 -218
- package/abi/RuntimeRBACDefinitions.abi.json +179 -0
- package/abi/SecureOwnable.abi.json +524 -1621
- package/abi/SecureOwnableDefinitions.abi.json +5 -0
- package/components/README.md +8 -0
- package/core/access/RuntimeRBAC.sol +255 -270
- package/core/access/interface/IRuntimeRBAC.sol +55 -84
- package/core/access/lib/definitions/RuntimeRBACDefinitions.sol +93 -2
- package/core/base/BaseStateMachine.sol +193 -107
- package/core/base/interface/IBaseStateMachine.sol +153 -153
- package/core/execution/GuardController.sol +155 -131
- package/core/execution/interface/IGuardController.sol +146 -120
- package/core/execution/lib/definitions/GuardControllerDefinitions.sol +193 -43
- package/core/lib/EngineBlox.sol +2683 -2322
- package/{interfaces → core/lib/interfaces}/IDefinition.sol +49 -49
- package/{interfaces → core/lib/interfaces}/IEventForwarder.sol +33 -33
- package/{utils → core/lib/utils}/SharedValidation.sol +61 -8
- package/core/pattern/Account.sol +84 -0
- package/core/security/SecureOwnable.sol +456 -412
- package/core/security/interface/ISecureOwnable.sol +105 -104
- package/core/security/lib/definitions/SecureOwnableDefinitions.sol +22 -6
- package/package.json +5 -5
- package/standards/README.md +12 -0
- package/standards/behavior/ICopyable.sol +34 -0
- package/standards/hooks/IOnActionHook.sol +21 -0
- package/abi/AccountBlox.abi.json +0 -5799
- package/abi/BareBlox.abi.json +0 -1284
- package/abi/RoleBlox.abi.json +0 -4209
- package/abi/SecureBlox.abi.json +0 -3828
- package/abi/SimpleRWA20.abi.json +0 -5288
- package/abi/SimpleRWA20Definitions.abi.json +0 -191
- package/abi/SimpleVault.abi.json +0 -4951
- package/core/research/BloxchainWallet.sol +0 -306
- package/core/research/erc20-blox/ERC20Blox.sol +0 -140
- package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +0 -185
- package/interfaces/IOnActionHook.sol +0 -79
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.
|
|
3
|
-
|
|
4
|
-
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
-
import "../
|
|
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.34;
|
|
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,33 +1,33 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.
|
|
3
|
-
|
|
4
|
-
// Import TxRecord struct from EngineBlox
|
|
5
|
-
import "../
|
|
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
|
-
}
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.34;
|
|
3
|
+
|
|
4
|
+
// Import TxRecord struct from EngineBlox
|
|
5
|
+
import "../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
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.
|
|
2
|
+
pragma solidity 0.8.34;
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @title SharedValidation
|
|
@@ -51,6 +51,8 @@ library SharedValidation {
|
|
|
51
51
|
error RestrictedRecovery(address caller, address recovery);
|
|
52
52
|
error RestrictedBroadcaster(address caller, address broadcaster);
|
|
53
53
|
error SignerNotAuthorized(address signer);
|
|
54
|
+
error MetaTxHandlerSelectorMismatch(bytes4 signedSelector, bytes4 entrySelector);
|
|
55
|
+
error MetaTxHandlerContractMismatch(address signedContract, address entryContract);
|
|
54
56
|
error OnlyCallableByContract(address caller, address contractAddress);
|
|
55
57
|
|
|
56
58
|
// Transaction and operation errors with context
|
|
@@ -59,6 +61,7 @@ library SharedValidation {
|
|
|
59
61
|
error ZeroOperationTypeNotAllowed();
|
|
60
62
|
error TransactionStatusMismatch(uint8 expectedStatus, uint8 currentStatus);
|
|
61
63
|
error AlreadyInitialized();
|
|
64
|
+
error NotInitialized();
|
|
62
65
|
error TransactionIdMismatch(uint256 expectedTxId, uint256 providedTxId);
|
|
63
66
|
error PendingSecureRequest();
|
|
64
67
|
|
|
@@ -72,6 +75,8 @@ library SharedValidation {
|
|
|
72
75
|
error InvalidVValue(uint8 v);
|
|
73
76
|
error ECDSAInvalidSignature(address recoveredSigner);
|
|
74
77
|
error GasPriceExceedsMax(uint256 currentGasPrice, uint256 maxGasPrice);
|
|
78
|
+
error MetaTxRecordMismatchStoredTx(uint256 txId);
|
|
79
|
+
error MetaTxPaymentMismatchStoredTx(uint256 txId);
|
|
75
80
|
|
|
76
81
|
// Consolidated resource errors
|
|
77
82
|
error ResourceNotFound(bytes32 resourceId);
|
|
@@ -82,13 +87,14 @@ library SharedValidation {
|
|
|
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
|
|
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
|
|
|
@@ -402,12 +455,12 @@ library SharedValidation {
|
|
|
402
455
|
// ============ UTILITY FUNCTIONS ============
|
|
403
456
|
|
|
404
457
|
/**
|
|
405
|
-
* @dev Validates that the first value is
|
|
406
|
-
* @param from The first value (
|
|
407
|
-
* @param to The second value (
|
|
458
|
+
* @dev Validates that the first value is not greater than the second (allows inclusive range: from <= to)
|
|
459
|
+
* @param from The first value (must be <= 'to' for a valid range)
|
|
460
|
+
* @param to The second value (must be >= 'from')
|
|
408
461
|
*/
|
|
409
462
|
function validateLessThan(uint256 from, uint256 to) internal pure {
|
|
410
|
-
if (from
|
|
463
|
+
if (from > to) revert InvalidRange(from, to);
|
|
411
464
|
}
|
|
412
465
|
|
|
413
466
|
/**
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
pragma solidity 0.8.34;
|
|
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
|
+
}
|