@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.
Files changed (55) hide show
  1. package/README.md +55 -18
  2. package/abi/{ControlBlox.abi.json → AccountBlox.abi.json} +699 -2974
  3. package/abi/BareBlox.abi.json +127 -90
  4. package/abi/BaseStateMachine.abi.json +127 -90
  5. package/abi/EngineBlox.abi.json +11 -31
  6. package/abi/GuardController.abi.json +217 -895
  7. package/abi/GuardControllerDefinitions.abi.json +380 -0
  8. package/abi/IDefinition.abi.json +19 -0
  9. package/abi/RoleBlox.abi.json +818 -2404
  10. package/abi/RuntimeRBAC.abi.json +122 -328
  11. package/abi/RuntimeRBACDefinitions.abi.json +243 -0
  12. package/abi/SecureBlox.abi.json +620 -1952
  13. package/abi/SecureOwnable.abi.json +469 -1801
  14. package/abi/SecureOwnableDefinitions.abi.json +57 -0
  15. package/abi/SimpleRWA20.abi.json +486 -1999
  16. package/abi/SimpleRWA20Definitions.abi.json +19 -0
  17. package/abi/SimpleVault.abi.json +884 -2685
  18. package/abi/SimpleVaultDefinitions.abi.json +19 -0
  19. package/components/README.md +8 -0
  20. package/core/access/RuntimeRBAC.sol +184 -0
  21. package/core/access/interface/IRuntimeRBAC.sol +55 -0
  22. package/{contracts/core → core}/access/lib/definitions/RuntimeRBACDefinitions.sol +121 -1
  23. package/{contracts/core → core}/base/BaseStateMachine.sol +187 -54
  24. package/{contracts/core → core}/base/interface/IBaseStateMachine.sol +7 -0
  25. package/{contracts/core → core}/execution/GuardController.sol +89 -155
  26. package/{contracts/core → core}/execution/interface/IGuardController.sol +52 -12
  27. package/{contracts/core → core}/execution/lib/definitions/GuardControllerDefinitions.sol +91 -2
  28. package/{contracts/core → core}/lib/EngineBlox.sol +167 -64
  29. package/{contracts → core/lib}/interfaces/IDefinition.sol +15 -6
  30. package/{contracts → core/lib}/interfaces/IEventForwarder.sol +1 -1
  31. package/{contracts → core/lib}/utils/SharedValidation.sol +490 -486
  32. package/core/pattern/Account.sol +75 -0
  33. package/core/research/BloxchainWallet.sol +133 -0
  34. package/core/research/FactoryBlox/FactoryBlox.sol +344 -0
  35. package/core/research/FactoryBlox/FactoryBloxDefinitions.sol +144 -0
  36. package/core/research/erc1155-blox/ERC1155Blox.sol +170 -0
  37. package/core/research/erc1155-blox/lib/definitions/ERC1155BloxDefinitions.sol +203 -0
  38. package/core/research/erc20-blox/ERC20Blox.sol +135 -0
  39. package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +185 -0
  40. package/core/research/erc721-blox/ERC721Blox.sol +131 -0
  41. package/core/research/erc721-blox/lib/definitions/ERC721BloxDefinitions.sol +172 -0
  42. package/core/research/lending-blox/.gitkeep +1 -0
  43. package/core/research/p2p-blox/P2PBlox.sol +266 -0
  44. package/core/research/p2p-blox/README.md +85 -0
  45. package/core/research/p2p-blox/lib/definitions/P2PBloxDefinitions.sol +19 -0
  46. package/{contracts/core → core}/security/SecureOwnable.sol +390 -419
  47. package/{contracts/core → core}/security/interface/ISecureOwnable.sol +27 -40
  48. package/{contracts/core → core}/security/lib/definitions/SecureOwnableDefinitions.sol +786 -757
  49. package/package.json +49 -47
  50. package/standards/README.md +12 -0
  51. package/standards/behavior/ICopyable.sol +36 -0
  52. package/standards/hooks/IOnActionHook.sol +21 -0
  53. package/contracts/core/access/RuntimeRBAC.sol +0 -344
  54. package/contracts/core/access/interface/IRuntimeRBAC.sol +0 -108
  55. package/contracts/interfaces/IOnActionHook.sol +0 -79
@@ -0,0 +1,144 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2025 Particle Crypto Security
3
+ pragma solidity 0.8.33;
4
+
5
+ import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
6
+ import "../../lib/EngineBlox.sol";
7
+ import "../../lib/interfaces/IDefinition.sol";
8
+
9
+ /**
10
+ * @title FactoryBloxDefinitions
11
+ * @dev Library containing definitions for FactoryBlox cloneBlox, whitelist, pricing, and macro registration.
12
+ *
13
+ * Registers cloneBlox, whitelist (addToWhitelist, removeFromWhitelist), and pricing (setClonePrice)
14
+ * function schemas. OWNER_ROLE gets EXECUTE_TIME_DELAY_REQUEST so requests go via the controller.
15
+ * All four are macro selectors so the controller can target address(this).
16
+ */
17
+ library FactoryBloxDefinitions {
18
+ bytes32 public constant CLONE_OPERATION = keccak256("CLONE_OPERATION");
19
+ bytes32 public constant WHITELIST_OPERATION = keccak256("WHITELIST_OPERATION");
20
+ bytes32 public constant CLONE_PRICE_OPERATION = keccak256("CLONE_PRICE_OPERATION");
21
+
22
+ /// @dev Macro selectors (allowed to target address(this) for GuardController execution)
23
+ bytes4 public constant CLONE_BLOX_SELECTOR =
24
+ bytes4(keccak256("cloneBlox(address,address,address,address,uint256,bytes)"));
25
+ // addToWhitelist(address,(address,uint256,address,uint256))
26
+ bytes4 public constant ADD_TO_WHITELIST_SELECTOR =
27
+ bytes4(keccak256("addToWhitelist(address,(address,uint256,address,uint256))"));
28
+ bytes4 public constant REMOVE_FROM_WHITELIST_SELECTOR = bytes4(keccak256("removeFromWhitelist(address)"));
29
+ // setClonePrice(address,(address,uint256,address,uint256))
30
+ bytes4 public constant SET_CLONE_PRICE_SELECTOR =
31
+ bytes4(keccak256("setClonePrice(address,(address,uint256,address,uint256))"));
32
+
33
+ function getFunctionSchemas() public pure returns (EngineBlox.FunctionSchema[] memory) {
34
+ EngineBlox.FunctionSchema[] memory schemas = new EngineBlox.FunctionSchema[](4);
35
+
36
+ EngineBlox.TxAction[] memory timeDelayRequestActions = new EngineBlox.TxAction[](1);
37
+ timeDelayRequestActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
38
+
39
+ bytes4[] memory cloneHandlers = new bytes4[](1);
40
+ cloneHandlers[0] = CLONE_BLOX_SELECTOR;
41
+ schemas[0] = EngineBlox.FunctionSchema({
42
+ functionSignature: "cloneBlox(address,address,address,address,uint256,bytes)",
43
+ functionSelector: CLONE_BLOX_SELECTOR,
44
+ operationType: CLONE_OPERATION,
45
+ operationName: "CLONE_OPERATION",
46
+ supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
47
+ isProtected: true,
48
+ handlerForSelectors: cloneHandlers
49
+ });
50
+
51
+ bytes4[] memory addWhitelistHandlers = new bytes4[](1);
52
+ addWhitelistHandlers[0] = ADD_TO_WHITELIST_SELECTOR;
53
+ schemas[1] = EngineBlox.FunctionSchema({
54
+ functionSignature: "addToWhitelist(address,(address,uint256,address,uint256))",
55
+ functionSelector: ADD_TO_WHITELIST_SELECTOR,
56
+ operationType: WHITELIST_OPERATION,
57
+ operationName: "WHITELIST_OPERATION",
58
+ supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
59
+ isProtected: true,
60
+ handlerForSelectors: addWhitelistHandlers
61
+ });
62
+
63
+ bytes4[] memory removeWhitelistHandlers = new bytes4[](1);
64
+ removeWhitelistHandlers[0] = REMOVE_FROM_WHITELIST_SELECTOR;
65
+ schemas[2] = EngineBlox.FunctionSchema({
66
+ functionSignature: "removeFromWhitelist(address)",
67
+ functionSelector: REMOVE_FROM_WHITELIST_SELECTOR,
68
+ operationType: WHITELIST_OPERATION,
69
+ operationName: "WHITELIST_OPERATION",
70
+ supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
71
+ isProtected: true,
72
+ handlerForSelectors: removeWhitelistHandlers
73
+ });
74
+
75
+ // Schema 3: setClonePrice (per-implementation pricing configuration for cloneBlox)
76
+ bytes4[] memory setClonePriceHandlers = new bytes4[](1);
77
+ setClonePriceHandlers[0] = SET_CLONE_PRICE_SELECTOR;
78
+ schemas[3] = EngineBlox.FunctionSchema({
79
+ functionSignature: "setClonePrice(address,(address,uint256,address,uint256))",
80
+ functionSelector: SET_CLONE_PRICE_SELECTOR,
81
+ operationType: CLONE_PRICE_OPERATION,
82
+ operationName: "CLONE_PRICE_OPERATION",
83
+ supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
84
+ isProtected: true,
85
+ handlerForSelectors: setClonePriceHandlers
86
+ });
87
+
88
+ return schemas;
89
+ }
90
+
91
+ function getRolePermissions() public pure returns (IDefinition.RolePermission memory) {
92
+ bytes32[] memory roleHashes = new bytes32[](4);
93
+ EngineBlox.FunctionPermission[] memory functionPermissions = new EngineBlox.FunctionPermission[](4);
94
+
95
+ EngineBlox.TxAction[] memory ownerRequestActions = new EngineBlox.TxAction[](1);
96
+ ownerRequestActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
97
+
98
+ roleHashes[0] = EngineBlox.OWNER_ROLE;
99
+ bytes4[] memory cloneHandlers = new bytes4[](1);
100
+ cloneHandlers[0] = CLONE_BLOX_SELECTOR;
101
+ functionPermissions[0] = EngineBlox.FunctionPermission({
102
+ functionSelector: CLONE_BLOX_SELECTOR,
103
+ grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
104
+ handlerForSelectors: cloneHandlers
105
+ });
106
+
107
+ roleHashes[1] = EngineBlox.OWNER_ROLE;
108
+ bytes4[] memory addWhitelistHandlers = new bytes4[](1);
109
+ addWhitelistHandlers[0] = ADD_TO_WHITELIST_SELECTOR;
110
+ functionPermissions[1] = EngineBlox.FunctionPermission({
111
+ functionSelector: ADD_TO_WHITELIST_SELECTOR,
112
+ grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
113
+ handlerForSelectors: addWhitelistHandlers
114
+ });
115
+
116
+ roleHashes[2] = EngineBlox.OWNER_ROLE;
117
+ bytes4[] memory removeWhitelistHandlers = new bytes4[](1);
118
+ removeWhitelistHandlers[0] = REMOVE_FROM_WHITELIST_SELECTOR;
119
+ functionPermissions[2] = EngineBlox.FunctionPermission({
120
+ functionSelector: REMOVE_FROM_WHITELIST_SELECTOR,
121
+ grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
122
+ handlerForSelectors: removeWhitelistHandlers
123
+ });
124
+
125
+ // Owner: setClonePrice
126
+ roleHashes[3] = EngineBlox.OWNER_ROLE;
127
+ bytes4[] memory setClonePriceHandlers = new bytes4[](1);
128
+ setClonePriceHandlers[0] = SET_CLONE_PRICE_SELECTOR;
129
+ functionPermissions[3] = EngineBlox.FunctionPermission({
130
+ functionSelector: SET_CLONE_PRICE_SELECTOR,
131
+ grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
132
+ handlerForSelectors: setClonePriceHandlers
133
+ });
134
+
135
+ return IDefinition.RolePermission({
136
+ roleHashes: roleHashes,
137
+ functionPermissions: functionPermissions
138
+ });
139
+ }
140
+
141
+ function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
142
+ return interfaceId == type(IERC165).interfaceId || interfaceId == type(IDefinition).interfaceId;
143
+ }
144
+ }
@@ -0,0 +1,170 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2025 Particle Crypto Security
3
+ pragma solidity 0.8.33;
4
+
5
+ // OpenZeppelin
6
+ import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
7
+ import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol";
8
+ import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
9
+ import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
10
+
11
+ // Core
12
+ import "../../security/SecureOwnable.sol";
13
+ import "../../access/RuntimeRBAC.sol";
14
+ import "../../execution/GuardController.sol";
15
+ import "../../base/BaseStateMachine.sol";
16
+ import "../../lib/interfaces/IDefinition.sol";
17
+ import "./lib/definitions/ERC1155BloxDefinitions.sol";
18
+
19
+ /**
20
+ * @title ERC1155Blox
21
+ * @dev ERC1155 multi-token (IERC1155) with SecureOwnable, RuntimeRBAC, and GuardController.
22
+ * Exposes safeTransferFrom, safeBatchTransferFrom (callable only via GuardController), mint/mintBatch (via controller), and burn/burnBatch (via controller).
23
+ * @custom:security-contact security@particlecrypto.com
24
+ */
25
+ contract ERC1155Blox is
26
+ IERC1155,
27
+ ERC1155Upgradeable,
28
+ ERC1155BurnableUpgradeable,
29
+ SecureOwnable,
30
+ RuntimeRBAC,
31
+ GuardController
32
+ {
33
+ /// @custom:oz-upgrades-unsafe-allow constructor
34
+ constructor() {
35
+ _disableInitializers();
36
+ }
37
+
38
+ /**
39
+ * @dev Override to resolve diamond: SecureOwnable, RuntimeRBAC, GuardController all define initialize(5 params).
40
+ * Call this first, then initializeToken(uri) to set ERC1155 base URI.
41
+ */
42
+ function initialize(
43
+ address initialOwner,
44
+ address broadcaster,
45
+ address recovery,
46
+ uint256 timeLockPeriodSec,
47
+ address eventForwarder
48
+ ) public virtual override(GuardController, RuntimeRBAC, SecureOwnable) initializer {
49
+ GuardController.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
50
+ RuntimeRBAC.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
51
+ SecureOwnable.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
52
+
53
+ IDefinition.RolePermission memory erc1155Permissions = ERC1155BloxDefinitions.getRolePermissions();
54
+ _loadDefinitions(
55
+ ERC1155BloxDefinitions.getFunctionSchemas(),
56
+ erc1155Permissions.roleHashes,
57
+ erc1155Permissions.functionPermissions,
58
+ true
59
+ );
60
+
61
+ _addMacroSelector(ERC1155BloxDefinitions.SAFE_TRANSFER_FROM_SELECTOR);
62
+ _addMacroSelector(ERC1155BloxDefinitions.SAFE_BATCH_TRANSFER_FROM_SELECTOR);
63
+ _addMacroSelector(ERC1155BloxDefinitions.MINT_SELECTOR);
64
+ _addMacroSelector(ERC1155BloxDefinitions.MINT_BATCH_SELECTOR);
65
+ _addMacroSelector(ERC1155BloxDefinitions.BURN_SELECTOR);
66
+ _addMacroSelector(ERC1155BloxDefinitions.BURN_BATCH_SELECTOR);
67
+ }
68
+
69
+ /**
70
+ * @notice Initialize the ERC1155 base URI. Call after initialize(5 params).
71
+ * @param uri_ Base URI for token metadata (e.g. https://example.com/{id}.json)
72
+ */
73
+ function initializeToken(string memory uri_) public reinitializer(2) {
74
+ __ERC1155_init(uri_);
75
+ }
76
+
77
+ /**
78
+ * @notice Safe transfer of token; callable only by this contract via GuardController
79
+ * @param from Sender address
80
+ * @param to Recipient address
81
+ * @param id Token type ID
82
+ * @param value Amount to transfer
83
+ * @param data Additional data for recipient hook
84
+ */
85
+ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)
86
+ public
87
+ virtual
88
+ override(ERC1155Upgradeable, IERC1155)
89
+ {
90
+ _validateExecuteBySelf();
91
+ super.safeTransferFrom(from, to, id, value, data);
92
+ }
93
+
94
+ /**
95
+ * @notice Safe batch transfer; callable only by this contract via GuardController
96
+ * @param from Sender address
97
+ * @param to Recipient address
98
+ * @param ids Token type IDs
99
+ * @param values Amounts to transfer
100
+ * @param data Additional data for recipient hook
101
+ */
102
+ function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data)
103
+ public
104
+ virtual
105
+ override(ERC1155Upgradeable, IERC1155)
106
+ {
107
+ _validateExecuteBySelf();
108
+ super.safeBatchTransferFrom(from, to, ids, values, data);
109
+ }
110
+
111
+ /**
112
+ * @notice Mint tokens to an account (callable only by this contract via GuardController)
113
+ * @param to Recipient address
114
+ * @param id Token type ID
115
+ * @param value Amount to mint
116
+ * @param data Additional data for recipient hook
117
+ */
118
+ function mint(address to, uint256 id, uint256 value, bytes memory data) external virtual {
119
+ _validateExecuteBySelf();
120
+ _mint(to, id, value, data);
121
+ }
122
+
123
+ /**
124
+ * @notice Mint batch of tokens (callable only by this contract via GuardController)
125
+ * @param to Recipient address
126
+ * @param ids Token type IDs
127
+ * @param values Amounts to mint
128
+ * @param data Additional data for recipient hook
129
+ */
130
+ function mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) external virtual {
131
+ _validateExecuteBySelf();
132
+ _mintBatch(to, ids, values, data);
133
+ }
134
+
135
+ /**
136
+ * @notice Burn tokens from an account (callable only by this contract via GuardController)
137
+ * @param account Account to burn from
138
+ * @param id Token type ID
139
+ * @param value Amount to burn
140
+ */
141
+ function burn(address account, uint256 id, uint256 value) public virtual override(ERC1155BurnableUpgradeable) {
142
+ _validateExecuteBySelf();
143
+ super.burn(account, id, value);
144
+ }
145
+
146
+ /**
147
+ * @notice Burn batch of tokens (callable only by this contract via GuardController)
148
+ * @param account Account to burn from
149
+ * @param ids Token type IDs
150
+ * @param values Amounts to burn
151
+ */
152
+ function burnBatch(address account, uint256[] memory ids, uint256[] memory values)
153
+ public
154
+ virtual
155
+ override(ERC1155BurnableUpgradeable)
156
+ {
157
+ _validateExecuteBySelf();
158
+ super.burnBatch(account, ids, values);
159
+ }
160
+
161
+ function supportsInterface(bytes4 interfaceId)
162
+ public
163
+ view
164
+ virtual
165
+ override(ERC1155Upgradeable, SecureOwnable, RuntimeRBAC, GuardController, IERC165)
166
+ returns (bool)
167
+ {
168
+ return interfaceId == type(IERC1155).interfaceId || super.supportsInterface(interfaceId) || GuardController.supportsInterface(interfaceId);
169
+ }
170
+ }
@@ -0,0 +1,203 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ pragma solidity 0.8.33;
3
+
4
+ import "../../../../lib/EngineBlox.sol";
5
+ import "../../../../lib/interfaces/IDefinition.sol";
6
+
7
+ /**
8
+ * @title ERC1155BloxDefinitions
9
+ * @dev Definition library for ERC1155Blox execution selectors (safeTransferFrom, safeBatchTransferFrom, mint, mintBatch, burn, burnBatch).
10
+ * Registers function schemas and role permissions so the GuardController can execute these functions
11
+ * via time-lock and meta-transaction workflows.
12
+ * @custom:security-contact security@particlecrypto.com
13
+ */
14
+ library ERC1155BloxDefinitions {
15
+
16
+ // System macro selectors (allowed to target address(this) for GuardController execution)
17
+ bytes4 public constant SAFE_TRANSFER_FROM_SELECTOR = bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)"));
18
+ bytes4 public constant SAFE_BATCH_TRANSFER_FROM_SELECTOR = bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"));
19
+ bytes4 public constant MINT_SELECTOR = bytes4(keccak256("mint(address,uint256,uint256,bytes)"));
20
+ bytes4 public constant MINT_BATCH_SELECTOR = bytes4(keccak256("mintBatch(address,uint256[],uint256[],bytes)"));
21
+ bytes4 public constant BURN_SELECTOR = bytes4(keccak256("burn(address,uint256,uint256)"));
22
+ bytes4 public constant BURN_BATCH_SELECTOR = bytes4(keccak256("burnBatch(address,uint256[],uint256[])"));
23
+
24
+ bytes32 public constant ERC1155_OPERATION = keccak256("ERC1155_OPERATION");
25
+
26
+ /**
27
+ * @dev Returns function schemas for ERC1155Blox execution selectors (used by controller).
28
+ */
29
+ function getFunctionSchemas() public pure returns (EngineBlox.FunctionSchema[] memory) {
30
+ EngineBlox.FunctionSchema[] memory schemas = new EngineBlox.FunctionSchema[](6);
31
+
32
+ EngineBlox.TxAction[] memory timeDelayRequestActions = new EngineBlox.TxAction[](1);
33
+ timeDelayRequestActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
34
+ EngineBlox.TxAction[] memory timeDelayApproveActions = new EngineBlox.TxAction[](1);
35
+ timeDelayApproveActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_APPROVE;
36
+ EngineBlox.TxAction[] memory timeDelayCancelActions = new EngineBlox.TxAction[](1);
37
+ timeDelayCancelActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_CANCEL;
38
+ EngineBlox.TxAction[] memory metaTxRequestApproveActions = new EngineBlox.TxAction[](2);
39
+ metaTxRequestApproveActions[0] = EngineBlox.TxAction.SIGN_META_REQUEST_AND_APPROVE;
40
+ metaTxRequestApproveActions[1] = EngineBlox.TxAction.EXECUTE_META_REQUEST_AND_APPROVE;
41
+ EngineBlox.TxAction[] memory metaTxApproveActions = new EngineBlox.TxAction[](2);
42
+ metaTxApproveActions[0] = EngineBlox.TxAction.SIGN_META_APPROVE;
43
+ metaTxApproveActions[1] = EngineBlox.TxAction.EXECUTE_META_APPROVE;
44
+ EngineBlox.TxAction[] memory metaTxCancelActions = new EngineBlox.TxAction[](2);
45
+ metaTxCancelActions[0] = EngineBlox.TxAction.SIGN_META_CANCEL;
46
+ metaTxCancelActions[1] = EngineBlox.TxAction.EXECUTE_META_CANCEL;
47
+
48
+ uint16 actionsBitmap = EngineBlox.createBitmapFromActions(timeDelayRequestActions)
49
+ | EngineBlox.createBitmapFromActions(timeDelayApproveActions)
50
+ | EngineBlox.createBitmapFromActions(timeDelayCancelActions)
51
+ | EngineBlox.createBitmapFromActions(metaTxRequestApproveActions)
52
+ | EngineBlox.createBitmapFromActions(metaTxApproveActions)
53
+ | EngineBlox.createBitmapFromActions(metaTxCancelActions);
54
+
55
+ bytes4[] memory safeTransferFromHandlers = new bytes4[](1);
56
+ safeTransferFromHandlers[0] = SAFE_TRANSFER_FROM_SELECTOR;
57
+ bytes4[] memory safeBatchTransferFromHandlers = new bytes4[](1);
58
+ safeBatchTransferFromHandlers[0] = SAFE_BATCH_TRANSFER_FROM_SELECTOR;
59
+ bytes4[] memory mintHandlers = new bytes4[](1);
60
+ mintHandlers[0] = MINT_SELECTOR;
61
+ bytes4[] memory mintBatchHandlers = new bytes4[](1);
62
+ mintBatchHandlers[0] = MINT_BATCH_SELECTOR;
63
+ bytes4[] memory burnHandlers = new bytes4[](1);
64
+ burnHandlers[0] = BURN_SELECTOR;
65
+ bytes4[] memory burnBatchHandlers = new bytes4[](1);
66
+ burnBatchHandlers[0] = BURN_BATCH_SELECTOR;
67
+
68
+ schemas[0] = EngineBlox.FunctionSchema({
69
+ functionSignature: "safeTransferFrom(address,address,uint256,uint256,bytes)",
70
+ functionSelector: SAFE_TRANSFER_FROM_SELECTOR,
71
+ operationType: ERC1155_OPERATION,
72
+ operationName: "ERC1155_SAFE_TRANSFER_FROM",
73
+ supportedActionsBitmap: actionsBitmap,
74
+ isProtected: true,
75
+ handlerForSelectors: safeTransferFromHandlers
76
+ });
77
+ schemas[1] = EngineBlox.FunctionSchema({
78
+ functionSignature: "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)",
79
+ functionSelector: SAFE_BATCH_TRANSFER_FROM_SELECTOR,
80
+ operationType: ERC1155_OPERATION,
81
+ operationName: "ERC1155_SAFE_BATCH_TRANSFER_FROM",
82
+ supportedActionsBitmap: actionsBitmap,
83
+ isProtected: true,
84
+ handlerForSelectors: safeBatchTransferFromHandlers
85
+ });
86
+ schemas[2] = EngineBlox.FunctionSchema({
87
+ functionSignature: "mint(address,uint256,uint256,bytes)",
88
+ functionSelector: MINT_SELECTOR,
89
+ operationType: ERC1155_OPERATION,
90
+ operationName: "ERC1155_MINT",
91
+ supportedActionsBitmap: actionsBitmap,
92
+ isProtected: true,
93
+ handlerForSelectors: mintHandlers
94
+ });
95
+ schemas[3] = EngineBlox.FunctionSchema({
96
+ functionSignature: "mintBatch(address,uint256[],uint256[],bytes)",
97
+ functionSelector: MINT_BATCH_SELECTOR,
98
+ operationType: ERC1155_OPERATION,
99
+ operationName: "ERC1155_MINT_BATCH",
100
+ supportedActionsBitmap: actionsBitmap,
101
+ isProtected: true,
102
+ handlerForSelectors: mintBatchHandlers
103
+ });
104
+ schemas[4] = EngineBlox.FunctionSchema({
105
+ functionSignature: "burn(address,uint256,uint256)",
106
+ functionSelector: BURN_SELECTOR,
107
+ operationType: ERC1155_OPERATION,
108
+ operationName: "ERC1155_BURN",
109
+ supportedActionsBitmap: actionsBitmap,
110
+ isProtected: true,
111
+ handlerForSelectors: burnHandlers
112
+ });
113
+ schemas[5] = EngineBlox.FunctionSchema({
114
+ functionSignature: "burnBatch(address,uint256[],uint256[])",
115
+ functionSelector: BURN_BATCH_SELECTOR,
116
+ operationType: ERC1155_OPERATION,
117
+ operationName: "ERC1155_BURN_BATCH",
118
+ supportedActionsBitmap: actionsBitmap,
119
+ isProtected: true,
120
+ handlerForSelectors: burnBatchHandlers
121
+ });
122
+
123
+ return schemas;
124
+ }
125
+
126
+ /**
127
+ * @dev Returns role permissions for ERC1155Blox execution selectors (OWNER and BROADCASTER).
128
+ */
129
+ function getRolePermissions() public pure returns (IDefinition.RolePermission memory) {
130
+ bytes32[] memory roleHashes = new bytes32[](12);
131
+ EngineBlox.FunctionPermission[] memory functionPermissions = new EngineBlox.FunctionPermission[](12);
132
+
133
+ EngineBlox.TxAction[] memory ownerTimeLockRequest = new EngineBlox.TxAction[](1);
134
+ ownerTimeLockRequest[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
135
+ EngineBlox.TxAction[] memory ownerTimeLockApprove = new EngineBlox.TxAction[](1);
136
+ ownerTimeLockApprove[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_APPROVE;
137
+ EngineBlox.TxAction[] memory ownerTimeLockCancel = new EngineBlox.TxAction[](1);
138
+ ownerTimeLockCancel[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_CANCEL;
139
+ EngineBlox.TxAction[] memory ownerMetaSign = new EngineBlox.TxAction[](1);
140
+ ownerMetaSign[0] = EngineBlox.TxAction.SIGN_META_REQUEST_AND_APPROVE;
141
+ EngineBlox.TxAction[] memory ownerMetaApprove = new EngineBlox.TxAction[](1);
142
+ ownerMetaApprove[0] = EngineBlox.TxAction.SIGN_META_APPROVE;
143
+ EngineBlox.TxAction[] memory ownerMetaCancel = new EngineBlox.TxAction[](1);
144
+ ownerMetaCancel[0] = EngineBlox.TxAction.SIGN_META_CANCEL;
145
+ EngineBlox.TxAction[] memory broadcasterMetaExec = new EngineBlox.TxAction[](1);
146
+ broadcasterMetaExec[0] = EngineBlox.TxAction.EXECUTE_META_REQUEST_AND_APPROVE;
147
+ EngineBlox.TxAction[] memory broadcasterMetaApprove = new EngineBlox.TxAction[](1);
148
+ broadcasterMetaApprove[0] = EngineBlox.TxAction.EXECUTE_META_APPROVE;
149
+ EngineBlox.TxAction[] memory broadcasterMetaCancel = new EngineBlox.TxAction[](1);
150
+ broadcasterMetaCancel[0] = EngineBlox.TxAction.EXECUTE_META_CANCEL;
151
+
152
+ uint16 ownerBitmap = EngineBlox.createBitmapFromActions(ownerTimeLockRequest)
153
+ | EngineBlox.createBitmapFromActions(ownerTimeLockApprove)
154
+ | EngineBlox.createBitmapFromActions(ownerTimeLockCancel)
155
+ | EngineBlox.createBitmapFromActions(ownerMetaSign)
156
+ | EngineBlox.createBitmapFromActions(ownerMetaApprove)
157
+ | EngineBlox.createBitmapFromActions(ownerMetaCancel);
158
+ uint16 broadcasterBitmap = EngineBlox.createBitmapFromActions(broadcasterMetaExec)
159
+ | EngineBlox.createBitmapFromActions(broadcasterMetaApprove)
160
+ | EngineBlox.createBitmapFromActions(broadcasterMetaCancel);
161
+
162
+ bytes4[6] memory selectors = [
163
+ SAFE_TRANSFER_FROM_SELECTOR,
164
+ SAFE_BATCH_TRANSFER_FROM_SELECTOR,
165
+ MINT_SELECTOR,
166
+ MINT_BATCH_SELECTOR,
167
+ BURN_SELECTOR,
168
+ BURN_BATCH_SELECTOR
169
+ ];
170
+ for (uint256 i = 0; i < 6; i++) {
171
+ bytes4[] memory selfRef = new bytes4[](1);
172
+ selfRef[0] = selectors[i];
173
+ roleHashes[i] = EngineBlox.OWNER_ROLE;
174
+ functionPermissions[i] = EngineBlox.FunctionPermission({
175
+ functionSelector: selectors[i],
176
+ grantedActionsBitmap: ownerBitmap,
177
+ handlerForSelectors: selfRef
178
+ });
179
+ }
180
+ for (uint256 i = 0; i < 6; i++) {
181
+ bytes4[] memory selfRef = new bytes4[](1);
182
+ selfRef[0] = selectors[i];
183
+ roleHashes[6 + i] = EngineBlox.BROADCASTER_ROLE;
184
+ functionPermissions[6 + i] = EngineBlox.FunctionPermission({
185
+ functionSelector: selectors[i],
186
+ grantedActionsBitmap: broadcasterBitmap,
187
+ handlerForSelectors: selfRef
188
+ });
189
+ }
190
+
191
+ return IDefinition.RolePermission({
192
+ roleHashes: roleHashes,
193
+ functionPermissions: functionPermissions
194
+ });
195
+ }
196
+
197
+ /**
198
+ * @dev ERC165: report support for IDefinition when this library is used at an address
199
+ */
200
+ function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
201
+ return interfaceId == type(IDefinition).interfaceId;
202
+ }
203
+ }
@@ -0,0 +1,135 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2025 Particle Crypto Security
3
+ pragma solidity 0.8.33;
4
+
5
+ // OpenZeppelin
6
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
7
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
8
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9
+
10
+ // Core
11
+ import "../../pattern/Account.sol";
12
+ import "../../lib/interfaces/IDefinition.sol";
13
+ import "../../lib/utils/SharedValidation.sol";
14
+ import "./lib/definitions/ERC20BloxDefinitions.sol";
15
+
16
+ // Standards
17
+ import "../../../standards/behavior/ICopyable.sol";
18
+
19
+ /**
20
+ * @title ERC20Blox
21
+ * @dev ERC20 token (IERC20) with Account pattern and ICopyable for cloning.
22
+ * Exposes transfer (ERC20), mint (owner-only), and burn (ERC20Burnable).
23
+ * @custom:security-contact security@particlecrypto.com
24
+ */
25
+ contract ERC20Blox is
26
+ IERC20,
27
+ ICopyable,
28
+ ERC20Upgradeable,
29
+ ERC20BurnableUpgradeable,
30
+ Account
31
+ {
32
+ /// @custom:oz-upgrades-unsafe-allow constructor
33
+ constructor() {
34
+ _disableInitializers();
35
+ }
36
+
37
+ /**
38
+ * @dev ICopyable: full init with custom data. initData must be abi.encode(name, symbol).
39
+ * Runs Account init, ERC20Blox definitions, and ERC20 name/symbol in one step.
40
+ */
41
+ function initializeWithData(
42
+ address initialOwner,
43
+ address broadcaster,
44
+ address recovery,
45
+ uint256 timeLockPeriodSec,
46
+ address eventForwarder,
47
+ bytes calldata initData
48
+ ) external virtual initializer {
49
+ super.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
50
+
51
+ IDefinition.RolePermission memory erc20Permissions = ERC20BloxDefinitions.getRolePermissions();
52
+ _loadDefinitions(
53
+ ERC20BloxDefinitions.getFunctionSchemas(),
54
+ erc20Permissions.roleHashes,
55
+ erc20Permissions.functionPermissions,
56
+ true
57
+ );
58
+
59
+ // Add macro selectors for the ERC20Blox definitions
60
+ _addMacroSelector(ERC20BloxDefinitions.TRANSFER_SELECTOR);
61
+ _addMacroSelector(ERC20BloxDefinitions.TRANSFER_FROM_SELECTOR);
62
+ _addMacroSelector(ERC20BloxDefinitions.MINT_SELECTOR);
63
+ _addMacroSelector(ERC20BloxDefinitions.BURN_SELECTOR);
64
+ _addMacroSelector(ERC20BloxDefinitions.BURN_FROM_SELECTOR);
65
+ (string memory name, string memory symbol) = abi.decode(initData, (string, string));
66
+ __ERC20_init(name, symbol);
67
+ }
68
+
69
+ /**
70
+ * @notice Transfer tokens to an account (callable only by this contract via GuardController)
71
+ * @param to Recipient address
72
+ * @param value Amount to transfer
73
+ */
74
+ function transfer(address to, uint256 value) public virtual override(ERC20Upgradeable, IERC20) returns (bool) {
75
+ _validateExecuteBySelf();
76
+ return super.transfer(to, value);
77
+ }
78
+
79
+ /**
80
+ * @notice Transfer tokens from one account to another (with allowance); callable only by this contract via GuardController
81
+ * @param from Sender address
82
+ * @param to Recipient address
83
+ * @param value Amount to transfer
84
+ */
85
+ function transferFrom(address from, address to, uint256 value) public virtual override(ERC20Upgradeable, IERC20) returns (bool) {
86
+ _validateExecuteBySelf();
87
+ return super.transferFrom(from, to, value);
88
+ }
89
+
90
+ /**
91
+ * @notice Mint tokens to an account (callable only by this contract via GuardController)
92
+ * @param to Recipient address
93
+ * @param amount Amount to mint
94
+ */
95
+ function mint(address to, uint256 amount) external virtual {
96
+ _validateExecuteBySelf();
97
+ _mint(to, amount);
98
+ }
99
+
100
+ /**
101
+ * @notice Burn tokens from caller (callable only by this contract via GuardController)
102
+ * @param value Amount to burn
103
+ */
104
+ function burn(uint256 value) public virtual override(ERC20BurnableUpgradeable) {
105
+ _validateExecuteBySelf();
106
+ super.burn(value);
107
+ }
108
+
109
+ /**
110
+ * @notice Burn tokens from an account (with allowance); callable only by this contract via GuardController
111
+ * @param account Account to burn from
112
+ * @param value Amount to burn
113
+ */
114
+ function burnFrom(address account, uint256 value) public virtual override(ERC20BurnableUpgradeable) {
115
+ _validateExecuteBySelf();
116
+ super.burnFrom(account, value);
117
+ }
118
+
119
+ function supportsInterface(bytes4 interfaceId) public view virtual override(Account) returns (bool) {
120
+ return interfaceId == type(IERC20).interfaceId || interfaceId == type(ICopyable).interfaceId || super.supportsInterface(interfaceId);
121
+ }
122
+
123
+ /**
124
+ * @dev Base initialization (5 params only) is disallowed; use initializeWithData(..., initData) with abi.encode(name, symbol).
125
+ */
126
+ function initialize(
127
+ address initialOwner,
128
+ address broadcaster,
129
+ address recovery,
130
+ uint256 timeLockPeriodSec,
131
+ address eventForwarder
132
+ ) public virtual override(Account) initializer {
133
+ revert SharedValidation.NotSupported();
134
+ }
135
+ }