@bloxchain/contracts 1.0.0-alpha.7 → 1.0.0
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/CHANGELOG.md +19 -0
- package/README.md +8 -9
- package/abi/BaseStateMachine.abi.json +773 -822
- package/abi/EngineBlox.abi.json +562 -552
- package/abi/GuardController.abi.json +1597 -1609
- package/abi/GuardControllerDefinitions.abi.json +235 -199
- package/abi/IDefinition.abi.json +57 -47
- package/abi/RuntimeRBAC.abi.json +841 -842
- package/abi/RuntimeRBACDefinitions.abi.json +212 -202
- package/abi/SecureOwnable.abi.json +1365 -1349
- package/abi/SecureOwnableDefinitions.abi.json +174 -164
- package/core/AUDIT.md +45 -0
- package/core/access/RuntimeRBAC.sol +130 -61
- package/core/access/interface/IRuntimeRBAC.sol +3 -3
- package/core/access/lib/definitions/RuntimeRBACDefinitions.sol +7 -3
- package/core/base/BaseStateMachine.sol +971 -967
- package/core/base/interface/IBaseStateMachine.sol +153 -160
- package/core/execution/GuardController.sol +89 -75
- package/core/execution/interface/IGuardController.sol +146 -160
- package/core/execution/lib/definitions/GuardControllerDefinitions.sol +136 -25
- package/core/lib/EngineBlox.sol +577 -327
- package/core/lib/interfaces/IDefinition.sol +49 -49
- package/core/lib/interfaces/IEventForwarder.sol +4 -2
- package/core/lib/utils/SharedValidation.sol +534 -490
- package/core/pattern/Account.sol +84 -75
- package/core/security/SecureOwnable.sol +446 -390
- package/core/security/interface/ISecureOwnable.sol +105 -105
- package/core/security/lib/definitions/SecureOwnableDefinitions.sol +49 -17
- package/package.json +51 -49
- package/standards/behavior/ICopyable.sol +3 -11
- package/standards/hooks/IOnActionHook.sol +1 -1
- package/abi/AccountBlox.abi.json +0 -3935
- package/abi/BareBlox.abi.json +0 -1378
- package/abi/RoleBlox.abi.json +0 -2983
- package/abi/SecureBlox.abi.json +0 -2753
- package/abi/SimpleRWA20.abi.json +0 -4032
- package/abi/SimpleRWA20Definitions.abi.json +0 -191
- package/abi/SimpleVault.abi.json +0 -3407
- package/abi/SimpleVaultDefinitions.abi.json +0 -269
- package/core/research/BloxchainWallet.sol +0 -133
- package/core/research/FactoryBlox/FactoryBlox.sol +0 -343
- package/core/research/FactoryBlox/FactoryBloxDefinitions.sol +0 -143
- package/core/research/erc1155-blox/ERC1155Blox.sol +0 -169
- package/core/research/erc1155-blox/lib/definitions/ERC1155BloxDefinitions.sol +0 -203
- package/core/research/erc20-blox/ERC20Blox.sol +0 -167
- package/core/research/erc20-blox/lib/definitions/ERC20BloxDefinitions.sol +0 -185
- package/core/research/erc721-blox/ERC721Blox.sol +0 -131
- package/core/research/erc721-blox/lib/definitions/ERC721BloxDefinitions.sol +0 -172
- package/core/research/lending-blox/.gitkeep +0 -1
- package/core/research/p2p-blox/P2PBlox.sol +0 -266
- package/core/research/p2p-blox/README.md +0 -85
- package/core/research/p2p-blox/lib/definitions/P2PBloxDefinitions.sol +0 -19
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.33;
|
|
3
|
-
|
|
4
|
-
import "@openzeppelin/contracts/proxy/Clones.sol";
|
|
5
|
-
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
|
|
6
|
-
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
|
|
7
|
-
import "../../execution/GuardController.sol";
|
|
8
|
-
import "../../access/RuntimeRBAC.sol";
|
|
9
|
-
import "../../security/SecureOwnable.sol";
|
|
10
|
-
import "../../base/interface/IBaseStateMachine.sol";
|
|
11
|
-
import "../../lib/EngineBlox.sol";
|
|
12
|
-
import "../../../standards/behavior/ICopyable.sol";
|
|
13
|
-
import "../../lib/interfaces/IDefinition.sol";
|
|
14
|
-
import "../../lib/interfaces/IEventForwarder.sol";
|
|
15
|
-
import "../../lib/utils/SharedValidation.sol";
|
|
16
|
-
import "./FactoryBloxDefinitions.sol";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @title FactoryBlox
|
|
20
|
-
* @dev CopyBlox-style blox factory with RBAC and GuardController like AccountBlox
|
|
21
|
-
*
|
|
22
|
-
* Combines:
|
|
23
|
-
* - GuardController: Execution workflows and time-locked transactions
|
|
24
|
-
* - RuntimeRBAC: Runtime role creation and management
|
|
25
|
-
* - SecureOwnable: Secure ownership transfer and management
|
|
26
|
-
* - Clone factory: Clone blox contracts (EIP-1167) with RBAC-protected cloneBlox
|
|
27
|
-
* - IEventForwarder: Centralize events from clones
|
|
28
|
-
*
|
|
29
|
-
* Only wallets with clone permission (OWNER_ROLE by default; custom roles via RuntimeRBAC)
|
|
30
|
-
* can call cloneBlox. Clones are initialized with eventForwarder set to this contract.
|
|
31
|
-
* When initData is non-empty, the implementation must support ICopyable and is initialized
|
|
32
|
-
* via initializeWithData; otherwise initialize(address,address,address,uint256,address) is used.
|
|
33
|
-
*
|
|
34
|
-
* clonesWhitelist: lightweight set of trusted blox implementation addresses. Only addresses in the
|
|
35
|
-
* whitelist can be cloned via cloneBlox, giving certainty about deploying the same contract.
|
|
36
|
-
* addToWhitelist and removeFromWhitelist are controller-only (macro + _validateExecuteBySelf).
|
|
37
|
-
*/
|
|
38
|
-
contract FactoryBlox is GuardController, RuntimeRBAC, SecureOwnable, IEventForwarder {
|
|
39
|
-
using Clones for address;
|
|
40
|
-
using ERC165Checker for address;
|
|
41
|
-
using EnumerableSet for EnumerableSet.AddressSet;
|
|
42
|
-
|
|
43
|
-
EnumerableSet.AddressSet private _clones;
|
|
44
|
-
/// @dev Trusted blox implementation addresses; only these can be cloned via cloneBlox
|
|
45
|
-
EnumerableSet.AddressSet private _clonesWhitelist;
|
|
46
|
-
/// @notice Whitelist entry containing implementation address and its configured clone price
|
|
47
|
-
struct CloneWhitelistEntry {
|
|
48
|
-
address bloxImplementation;
|
|
49
|
-
EngineBlox.PaymentDetails price;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/// @dev Per-implementation clone pricing configuration
|
|
53
|
-
mapping(address => EngineBlox.PaymentDetails) private _clonePrices;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @notice Initializer for FactoryBlox
|
|
57
|
-
*/
|
|
58
|
-
function initialize(
|
|
59
|
-
address initialOwner,
|
|
60
|
-
address broadcaster,
|
|
61
|
-
address recovery,
|
|
62
|
-
uint256 timeLockPeriodSec,
|
|
63
|
-
address eventForwarder
|
|
64
|
-
) public virtual override(GuardController, RuntimeRBAC, SecureOwnable) initializer {
|
|
65
|
-
GuardController.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
66
|
-
RuntimeRBAC.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
67
|
-
SecureOwnable.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
68
|
-
|
|
69
|
-
IDefinition.RolePermission memory factoryPermissions = FactoryBloxDefinitions.getRolePermissions();
|
|
70
|
-
_loadDefinitions(
|
|
71
|
-
FactoryBloxDefinitions.getFunctionSchemas(),
|
|
72
|
-
factoryPermissions.roleHashes,
|
|
73
|
-
factoryPermissions.functionPermissions,
|
|
74
|
-
true
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Register macro selectors so controller can target address(this) for time-lock/meta-tx execution
|
|
78
|
-
_addMacroSelector(FactoryBloxDefinitions.CLONE_BLOX_SELECTOR);
|
|
79
|
-
_addMacroSelector(FactoryBloxDefinitions.ADD_TO_WHITELIST_SELECTOR);
|
|
80
|
-
_addMacroSelector(FactoryBloxDefinitions.REMOVE_FROM_WHITELIST_SELECTOR);
|
|
81
|
-
|
|
82
|
-
// Allow cloning this factory's implementation (or proxy) by default
|
|
83
|
-
_clonesWhitelist.add(address(this));
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function supportsInterface(bytes4 interfaceId)
|
|
87
|
-
public
|
|
88
|
-
view
|
|
89
|
-
virtual
|
|
90
|
-
override(GuardController, RuntimeRBAC, SecureOwnable)
|
|
91
|
-
returns (bool)
|
|
92
|
-
{
|
|
93
|
-
return interfaceId == type(IEventForwarder).interfaceId
|
|
94
|
-
|| GuardController.supportsInterface(interfaceId)
|
|
95
|
-
|| RuntimeRBAC.supportsInterface(interfaceId)
|
|
96
|
-
|| SecureOwnable.supportsInterface(interfaceId);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* @notice Clone a blox contract (RBAC-protected). Caller must have clone permission (e.g. OWNER_ROLE).
|
|
101
|
-
* @param initData When non-empty, target must implement ICopyable and is initialized via initializeWithData; otherwise standard initialize(...) is used.
|
|
102
|
-
*/
|
|
103
|
-
function cloneBlox(
|
|
104
|
-
address bloxAddress,
|
|
105
|
-
address initialOwner,
|
|
106
|
-
address broadcaster,
|
|
107
|
-
address recovery,
|
|
108
|
-
uint256 timeLockPeriodSec,
|
|
109
|
-
bytes calldata initData
|
|
110
|
-
) external nonReentrant returns (address cloneAddress) {
|
|
111
|
-
_validateExecuteBySelf();
|
|
112
|
-
_validateBloxImplementation(bloxAddress);
|
|
113
|
-
|
|
114
|
-
if (initData.length > 0 && !bloxAddress.supportsInterface(type(ICopyable).interfaceId)) {
|
|
115
|
-
revert SharedValidation.InvalidOperation(bloxAddress);
|
|
116
|
-
}
|
|
117
|
-
if (!_clonesWhitelist.contains(bloxAddress)) {
|
|
118
|
-
revert SharedValidation.InvalidOperation(bloxAddress);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
cloneAddress = Clones.clone(bloxAddress);
|
|
122
|
-
address eventForwarder = address(this);
|
|
123
|
-
bool success;
|
|
124
|
-
|
|
125
|
-
if (initData.length > 0) {
|
|
126
|
-
success = _initializeCloneWithData(
|
|
127
|
-
cloneAddress,
|
|
128
|
-
initialOwner,
|
|
129
|
-
broadcaster,
|
|
130
|
-
recovery,
|
|
131
|
-
timeLockPeriodSec,
|
|
132
|
-
eventForwarder,
|
|
133
|
-
initData
|
|
134
|
-
);
|
|
135
|
-
} else {
|
|
136
|
-
success = _initializeClone(
|
|
137
|
-
cloneAddress,
|
|
138
|
-
initialOwner,
|
|
139
|
-
broadcaster,
|
|
140
|
-
recovery,
|
|
141
|
-
timeLockPeriodSec,
|
|
142
|
-
eventForwarder
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!success) revert SharedValidation.OperationFailed();
|
|
147
|
-
|
|
148
|
-
_clones.add(cloneAddress);
|
|
149
|
-
_logComponentEvent(abi.encode(bloxAddress, cloneAddress, initialOwner, _clones.length()));
|
|
150
|
-
return cloneAddress;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* @notice Add a trusted blox implementation to the whitelist with an associated clone price.
|
|
155
|
-
* Only callable by the controller (macro + _validateExecuteBySelf).
|
|
156
|
-
* @param bloxImplementation Address of the blox implementation contract (must be IBaseStateMachine, not zero, not this).
|
|
157
|
-
* @param price Per-clone payment configuration for this implementation.
|
|
158
|
-
*/
|
|
159
|
-
function addToWhitelist(address bloxImplementation, EngineBlox.PaymentDetails calldata price) external nonReentrant {
|
|
160
|
-
_validateExecuteBySelf();
|
|
161
|
-
_validateBloxImplementation(bloxImplementation);
|
|
162
|
-
if (_clonesWhitelist.add(bloxImplementation)) {
|
|
163
|
-
_clonePrices[bloxImplementation] = price;
|
|
164
|
-
_logComponentEvent(
|
|
165
|
-
abi.encode(
|
|
166
|
-
bloxImplementation,
|
|
167
|
-
price.recipient,
|
|
168
|
-
price.nativeTokenAmount,
|
|
169
|
-
price.erc20TokenAddress,
|
|
170
|
-
price.erc20TokenAmount
|
|
171
|
-
)
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* @notice Remove a blox implementation from the whitelist. Only callable by the controller (macro + _validateExecuteBySelf).
|
|
178
|
-
* @param bloxImplementation Address to remove from the whitelist.
|
|
179
|
-
*/
|
|
180
|
-
function removeFromWhitelist(address bloxImplementation) external nonReentrant {
|
|
181
|
-
_validateExecuteBySelf();
|
|
182
|
-
if (_clonesWhitelist.remove(bloxImplementation)) {
|
|
183
|
-
// Clear any configured price for the removed implementation
|
|
184
|
-
delete _clonePrices[bloxImplementation];
|
|
185
|
-
_logComponentEvent(abi.encode(bloxImplementation));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* @dev Validates that an address is a deployed contract implementing IBaseStateMachine.
|
|
191
|
-
*/
|
|
192
|
-
function _validateBloxImplementation(address bloxAddress) internal view {
|
|
193
|
-
if (!bloxAddress.supportsInterface(type(IBaseStateMachine).interfaceId)) {
|
|
194
|
-
revert SharedValidation.InvalidOperation(bloxAddress);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function _initializeClone(
|
|
199
|
-
address cloneAddress,
|
|
200
|
-
address initialOwner,
|
|
201
|
-
address broadcaster,
|
|
202
|
-
address recovery,
|
|
203
|
-
uint256 timeLockPeriodSec,
|
|
204
|
-
address eventForwarder
|
|
205
|
-
) internal returns (bool) {
|
|
206
|
-
(bool success, ) = cloneAddress.call(
|
|
207
|
-
abi.encodeWithSignature(
|
|
208
|
-
"initialize(address,address,address,uint256,address)",
|
|
209
|
-
initialOwner,
|
|
210
|
-
broadcaster,
|
|
211
|
-
recovery,
|
|
212
|
-
timeLockPeriodSec,
|
|
213
|
-
eventForwarder
|
|
214
|
-
)
|
|
215
|
-
);
|
|
216
|
-
return success;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function _initializeCloneWithData(
|
|
220
|
-
address cloneAddress,
|
|
221
|
-
address initialOwner,
|
|
222
|
-
address broadcaster,
|
|
223
|
-
address recovery,
|
|
224
|
-
uint256 timeLockPeriodSec,
|
|
225
|
-
address eventForwarder,
|
|
226
|
-
bytes calldata initData
|
|
227
|
-
) internal returns (bool) {
|
|
228
|
-
(bool success, ) = cloneAddress.call(
|
|
229
|
-
abi.encodeWithSignature(
|
|
230
|
-
"initializeWithData(address,address,address,uint256,address,bytes)",
|
|
231
|
-
initialOwner,
|
|
232
|
-
broadcaster,
|
|
233
|
-
recovery,
|
|
234
|
-
timeLockPeriodSec,
|
|
235
|
-
eventForwarder,
|
|
236
|
-
initData
|
|
237
|
-
)
|
|
238
|
-
);
|
|
239
|
-
return success;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function getCloneAtIndex(uint256 index) external view returns (address) {
|
|
243
|
-
return _clones.at(index);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function isClone(address cloneAddress) external view returns (bool) {
|
|
247
|
-
return _clones.contains(cloneAddress);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function getClonesCount() external view returns (uint256) {
|
|
251
|
-
return _clones.length();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function getWhitelistCount() external view returns (uint256) {
|
|
255
|
-
return _clonesWhitelist.length();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// function getWhitelistAtIndex(uint256 index) external view returns (address) {
|
|
259
|
-
// return _clonesWhitelist.at(index);
|
|
260
|
-
// }
|
|
261
|
-
|
|
262
|
-
function isWhitelisted(address bloxImplementation) external view returns (bool) {
|
|
263
|
-
return _clonesWhitelist.contains(bloxImplementation);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// /**
|
|
267
|
-
// * @notice Returns the configured clone price for a given blox implementation.
|
|
268
|
-
// * @dev Zero-valued fields indicate no explicit pricing (free clone) for this implementation.
|
|
269
|
-
// */
|
|
270
|
-
// function getClonePrice(address bloxImplementation) external view returns (EngineBlox.PaymentDetails memory) {
|
|
271
|
-
// return _clonePrices[bloxImplementation];
|
|
272
|
-
// }
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @notice Returns whitelist entry (implementation + price) at a given index.
|
|
276
|
-
*/
|
|
277
|
-
function getWhitelistEntryAtIndex(uint256 index) external view returns (CloneWhitelistEntry memory) {
|
|
278
|
-
address bloxImplementation = _clonesWhitelist.at(index);
|
|
279
|
-
return CloneWhitelistEntry({ bloxImplementation: bloxImplementation, price: _clonePrices[bloxImplementation] });
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @dev Post-action hook: when cloneBlox was requested with payment, verify the tx payment matches
|
|
284
|
-
* the configured per-implementation clone price. Ensures the requestor did not alter the payment
|
|
285
|
-
* (e.g. recipient or amounts). Only runs when TxStatus is COMPLETED (e.g. not on cancellation
|
|
286
|
-
* or failed execution).
|
|
287
|
-
*/
|
|
288
|
-
function _postActionHook(EngineBlox.TxRecord memory txRecord) internal virtual override {
|
|
289
|
-
if (txRecord.params.executionSelector != FactoryBloxDefinitions.CLONE_BLOX_SELECTOR) {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
if (txRecord.status != EngineBlox.TxStatus.COMPLETED) {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Decode the blox implementation address from execution params:
|
|
297
|
-
// cloneBlox(address bloxAddress, address initialOwner, address broadcaster, address recovery, uint256 timeLockPeriodSec, bytes initData)
|
|
298
|
-
(address bloxImplementation, , , , , ) = abi.decode(
|
|
299
|
-
txRecord.params.executionParams,
|
|
300
|
-
(address, address, address, address, uint256, bytes)
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
EngineBlox.PaymentDetails memory expectedPrice = _clonePrices[bloxImplementation];
|
|
304
|
-
EngineBlox.PaymentDetails memory payment = txRecord.payment;
|
|
305
|
-
|
|
306
|
-
if (
|
|
307
|
-
payment.recipient != expectedPrice.recipient
|
|
308
|
-
|| payment.nativeTokenAmount != expectedPrice.nativeTokenAmount
|
|
309
|
-
|| payment.erc20TokenAddress != expectedPrice.erc20TokenAddress
|
|
310
|
-
|| payment.erc20TokenAmount != expectedPrice.erc20TokenAmount
|
|
311
|
-
) {
|
|
312
|
-
revert SharedValidation.InvalidPayment();
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function forwardTxEvent(
|
|
317
|
-
uint256 txId,
|
|
318
|
-
bytes4 functionSelector,
|
|
319
|
-
EngineBlox.TxStatus status,
|
|
320
|
-
address requester,
|
|
321
|
-
address target,
|
|
322
|
-
bytes32 operationType
|
|
323
|
-
) external override {
|
|
324
|
-
if (!_clones.contains(msg.sender)) revert SharedValidation.NoPermission(msg.sender);
|
|
325
|
-
|
|
326
|
-
_logComponentEvent(abi.encode(msg.sender, txId, functionSelector, status, requester, target, operationType));
|
|
327
|
-
|
|
328
|
-
address eventForwarder = _secureState.eventForwarder;
|
|
329
|
-
if (eventForwarder != address(0) && eventForwarder != address(this)) {
|
|
330
|
-
try IEventForwarder(eventForwarder).forwardTxEvent(
|
|
331
|
-
txId, functionSelector, status, requester, target, operationType
|
|
332
|
-
) {} catch {}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
receive() external payable {}
|
|
337
|
-
|
|
338
|
-
fallback() external payable {
|
|
339
|
-
revert SharedValidation.NotSupported();
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
uint256[50] private __gap;
|
|
343
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.33;
|
|
3
|
-
|
|
4
|
-
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
-
import "../../lib/EngineBlox.sol";
|
|
6
|
-
import "../../lib/interfaces/IDefinition.sol";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @title FactoryBloxDefinitions
|
|
10
|
-
* @dev Library containing definitions for FactoryBlox cloneBlox, whitelist, pricing, and macro registration.
|
|
11
|
-
*
|
|
12
|
-
* Registers cloneBlox, whitelist (addToWhitelist, removeFromWhitelist), and pricing (setClonePrice)
|
|
13
|
-
* function schemas. OWNER_ROLE gets EXECUTE_TIME_DELAY_REQUEST so requests go via the controller.
|
|
14
|
-
* All four are macro selectors so the controller can target address(this).
|
|
15
|
-
*/
|
|
16
|
-
library FactoryBloxDefinitions {
|
|
17
|
-
bytes32 public constant CLONE_OPERATION = keccak256("CLONE_OPERATION");
|
|
18
|
-
bytes32 public constant WHITELIST_OPERATION = keccak256("WHITELIST_OPERATION");
|
|
19
|
-
bytes32 public constant CLONE_PRICE_OPERATION = keccak256("CLONE_PRICE_OPERATION");
|
|
20
|
-
|
|
21
|
-
/// @dev Macro selectors (allowed to target address(this) for GuardController execution)
|
|
22
|
-
bytes4 public constant CLONE_BLOX_SELECTOR =
|
|
23
|
-
bytes4(keccak256("cloneBlox(address,address,address,address,uint256,bytes)"));
|
|
24
|
-
// addToWhitelist(address,(address,uint256,address,uint256))
|
|
25
|
-
bytes4 public constant ADD_TO_WHITELIST_SELECTOR =
|
|
26
|
-
bytes4(keccak256("addToWhitelist(address,(address,uint256,address,uint256))"));
|
|
27
|
-
bytes4 public constant REMOVE_FROM_WHITELIST_SELECTOR = bytes4(keccak256("removeFromWhitelist(address)"));
|
|
28
|
-
// setClonePrice(address,(address,uint256,address,uint256))
|
|
29
|
-
bytes4 public constant SET_CLONE_PRICE_SELECTOR =
|
|
30
|
-
bytes4(keccak256("setClonePrice(address,(address,uint256,address,uint256))"));
|
|
31
|
-
|
|
32
|
-
function getFunctionSchemas() public pure returns (EngineBlox.FunctionSchema[] memory) {
|
|
33
|
-
EngineBlox.FunctionSchema[] memory schemas = new EngineBlox.FunctionSchema[](4);
|
|
34
|
-
|
|
35
|
-
EngineBlox.TxAction[] memory timeDelayRequestActions = new EngineBlox.TxAction[](1);
|
|
36
|
-
timeDelayRequestActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
|
|
37
|
-
|
|
38
|
-
bytes4[] memory cloneHandlers = new bytes4[](1);
|
|
39
|
-
cloneHandlers[0] = CLONE_BLOX_SELECTOR;
|
|
40
|
-
schemas[0] = EngineBlox.FunctionSchema({
|
|
41
|
-
functionSignature: "cloneBlox(address,address,address,address,uint256,bytes)",
|
|
42
|
-
functionSelector: CLONE_BLOX_SELECTOR,
|
|
43
|
-
operationType: CLONE_OPERATION,
|
|
44
|
-
operationName: "CLONE_OPERATION",
|
|
45
|
-
supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
|
|
46
|
-
isProtected: true,
|
|
47
|
-
handlerForSelectors: cloneHandlers
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
bytes4[] memory addWhitelistHandlers = new bytes4[](1);
|
|
51
|
-
addWhitelistHandlers[0] = ADD_TO_WHITELIST_SELECTOR;
|
|
52
|
-
schemas[1] = EngineBlox.FunctionSchema({
|
|
53
|
-
functionSignature: "addToWhitelist(address,(address,uint256,address,uint256))",
|
|
54
|
-
functionSelector: ADD_TO_WHITELIST_SELECTOR,
|
|
55
|
-
operationType: WHITELIST_OPERATION,
|
|
56
|
-
operationName: "WHITELIST_OPERATION",
|
|
57
|
-
supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
|
|
58
|
-
isProtected: true,
|
|
59
|
-
handlerForSelectors: addWhitelistHandlers
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
bytes4[] memory removeWhitelistHandlers = new bytes4[](1);
|
|
63
|
-
removeWhitelistHandlers[0] = REMOVE_FROM_WHITELIST_SELECTOR;
|
|
64
|
-
schemas[2] = EngineBlox.FunctionSchema({
|
|
65
|
-
functionSignature: "removeFromWhitelist(address)",
|
|
66
|
-
functionSelector: REMOVE_FROM_WHITELIST_SELECTOR,
|
|
67
|
-
operationType: WHITELIST_OPERATION,
|
|
68
|
-
operationName: "WHITELIST_OPERATION",
|
|
69
|
-
supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
|
|
70
|
-
isProtected: true,
|
|
71
|
-
handlerForSelectors: removeWhitelistHandlers
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Schema 3: setClonePrice (per-implementation pricing configuration for cloneBlox)
|
|
75
|
-
bytes4[] memory setClonePriceHandlers = new bytes4[](1);
|
|
76
|
-
setClonePriceHandlers[0] = SET_CLONE_PRICE_SELECTOR;
|
|
77
|
-
schemas[3] = EngineBlox.FunctionSchema({
|
|
78
|
-
functionSignature: "setClonePrice(address,(address,uint256,address,uint256))",
|
|
79
|
-
functionSelector: SET_CLONE_PRICE_SELECTOR,
|
|
80
|
-
operationType: CLONE_PRICE_OPERATION,
|
|
81
|
-
operationName: "CLONE_PRICE_OPERATION",
|
|
82
|
-
supportedActionsBitmap: EngineBlox.createBitmapFromActions(timeDelayRequestActions),
|
|
83
|
-
isProtected: true,
|
|
84
|
-
handlerForSelectors: setClonePriceHandlers
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return schemas;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function getRolePermissions() public pure returns (IDefinition.RolePermission memory) {
|
|
91
|
-
bytes32[] memory roleHashes = new bytes32[](4);
|
|
92
|
-
EngineBlox.FunctionPermission[] memory functionPermissions = new EngineBlox.FunctionPermission[](4);
|
|
93
|
-
|
|
94
|
-
EngineBlox.TxAction[] memory ownerRequestActions = new EngineBlox.TxAction[](1);
|
|
95
|
-
ownerRequestActions[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
|
|
96
|
-
|
|
97
|
-
roleHashes[0] = EngineBlox.OWNER_ROLE;
|
|
98
|
-
bytes4[] memory cloneHandlers = new bytes4[](1);
|
|
99
|
-
cloneHandlers[0] = CLONE_BLOX_SELECTOR;
|
|
100
|
-
functionPermissions[0] = EngineBlox.FunctionPermission({
|
|
101
|
-
functionSelector: CLONE_BLOX_SELECTOR,
|
|
102
|
-
grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
|
|
103
|
-
handlerForSelectors: cloneHandlers
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
roleHashes[1] = EngineBlox.OWNER_ROLE;
|
|
107
|
-
bytes4[] memory addWhitelistHandlers = new bytes4[](1);
|
|
108
|
-
addWhitelistHandlers[0] = ADD_TO_WHITELIST_SELECTOR;
|
|
109
|
-
functionPermissions[1] = EngineBlox.FunctionPermission({
|
|
110
|
-
functionSelector: ADD_TO_WHITELIST_SELECTOR,
|
|
111
|
-
grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
|
|
112
|
-
handlerForSelectors: addWhitelistHandlers
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
roleHashes[2] = EngineBlox.OWNER_ROLE;
|
|
116
|
-
bytes4[] memory removeWhitelistHandlers = new bytes4[](1);
|
|
117
|
-
removeWhitelistHandlers[0] = REMOVE_FROM_WHITELIST_SELECTOR;
|
|
118
|
-
functionPermissions[2] = EngineBlox.FunctionPermission({
|
|
119
|
-
functionSelector: REMOVE_FROM_WHITELIST_SELECTOR,
|
|
120
|
-
grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
|
|
121
|
-
handlerForSelectors: removeWhitelistHandlers
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Owner: setClonePrice
|
|
125
|
-
roleHashes[3] = EngineBlox.OWNER_ROLE;
|
|
126
|
-
bytes4[] memory setClonePriceHandlers = new bytes4[](1);
|
|
127
|
-
setClonePriceHandlers[0] = SET_CLONE_PRICE_SELECTOR;
|
|
128
|
-
functionPermissions[3] = EngineBlox.FunctionPermission({
|
|
129
|
-
functionSelector: SET_CLONE_PRICE_SELECTOR,
|
|
130
|
-
grantedActionsBitmap: EngineBlox.createBitmapFromActions(ownerRequestActions),
|
|
131
|
-
handlerForSelectors: setClonePriceHandlers
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return IDefinition.RolePermission({
|
|
135
|
-
roleHashes: roleHashes,
|
|
136
|
-
functionPermissions: functionPermissions
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
|
|
141
|
-
return interfaceId == type(IERC165).interfaceId || interfaceId == type(IDefinition).interfaceId;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.33;
|
|
3
|
-
|
|
4
|
-
// OpenZeppelin
|
|
5
|
-
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
|
|
6
|
-
import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155BurnableUpgradeable.sol";
|
|
7
|
-
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
|
|
8
|
-
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
9
|
-
|
|
10
|
-
// Core
|
|
11
|
-
import "../../security/SecureOwnable.sol";
|
|
12
|
-
import "../../access/RuntimeRBAC.sol";
|
|
13
|
-
import "../../execution/GuardController.sol";
|
|
14
|
-
import "../../base/BaseStateMachine.sol";
|
|
15
|
-
import "../../lib/interfaces/IDefinition.sol";
|
|
16
|
-
import "./lib/definitions/ERC1155BloxDefinitions.sol";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @title ERC1155Blox
|
|
20
|
-
* @dev ERC1155 multi-token (IERC1155) with SecureOwnable, RuntimeRBAC, and GuardController.
|
|
21
|
-
* Exposes safeTransferFrom, safeBatchTransferFrom (callable only via GuardController), mint/mintBatch (via controller), and burn/burnBatch (via controller).
|
|
22
|
-
* @custom:security-contact security@particlecrypto.com
|
|
23
|
-
*/
|
|
24
|
-
contract ERC1155Blox is
|
|
25
|
-
IERC1155,
|
|
26
|
-
ERC1155Upgradeable,
|
|
27
|
-
ERC1155BurnableUpgradeable,
|
|
28
|
-
SecureOwnable,
|
|
29
|
-
RuntimeRBAC,
|
|
30
|
-
GuardController
|
|
31
|
-
{
|
|
32
|
-
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
33
|
-
constructor() {
|
|
34
|
-
_disableInitializers();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @dev Override to resolve diamond: SecureOwnable, RuntimeRBAC, GuardController all define initialize(5 params).
|
|
39
|
-
* Call this first, then initializeToken(uri) to set ERC1155 base URI.
|
|
40
|
-
*/
|
|
41
|
-
function initialize(
|
|
42
|
-
address initialOwner,
|
|
43
|
-
address broadcaster,
|
|
44
|
-
address recovery,
|
|
45
|
-
uint256 timeLockPeriodSec,
|
|
46
|
-
address eventForwarder
|
|
47
|
-
) public virtual override(GuardController, RuntimeRBAC, SecureOwnable) initializer {
|
|
48
|
-
GuardController.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
49
|
-
RuntimeRBAC.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
50
|
-
SecureOwnable.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
51
|
-
|
|
52
|
-
IDefinition.RolePermission memory erc1155Permissions = ERC1155BloxDefinitions.getRolePermissions();
|
|
53
|
-
_loadDefinitions(
|
|
54
|
-
ERC1155BloxDefinitions.getFunctionSchemas(),
|
|
55
|
-
erc1155Permissions.roleHashes,
|
|
56
|
-
erc1155Permissions.functionPermissions,
|
|
57
|
-
true
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
_addMacroSelector(ERC1155BloxDefinitions.SAFE_TRANSFER_FROM_SELECTOR);
|
|
61
|
-
_addMacroSelector(ERC1155BloxDefinitions.SAFE_BATCH_TRANSFER_FROM_SELECTOR);
|
|
62
|
-
_addMacroSelector(ERC1155BloxDefinitions.MINT_SELECTOR);
|
|
63
|
-
_addMacroSelector(ERC1155BloxDefinitions.MINT_BATCH_SELECTOR);
|
|
64
|
-
_addMacroSelector(ERC1155BloxDefinitions.BURN_SELECTOR);
|
|
65
|
-
_addMacroSelector(ERC1155BloxDefinitions.BURN_BATCH_SELECTOR);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* @notice Initialize the ERC1155 base URI. Call after initialize(5 params).
|
|
70
|
-
* @param uri_ Base URI for token metadata (e.g. https://example.com/{id}.json)
|
|
71
|
-
*/
|
|
72
|
-
function initializeToken(string memory uri_) public reinitializer(2) {
|
|
73
|
-
__ERC1155_init(uri_);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @notice Safe transfer of token; callable only by this contract via GuardController
|
|
78
|
-
* @param from Sender address
|
|
79
|
-
* @param to Recipient address
|
|
80
|
-
* @param id Token type ID
|
|
81
|
-
* @param value Amount to transfer
|
|
82
|
-
* @param data Additional data for recipient hook
|
|
83
|
-
*/
|
|
84
|
-
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)
|
|
85
|
-
public
|
|
86
|
-
virtual
|
|
87
|
-
override(ERC1155Upgradeable, IERC1155)
|
|
88
|
-
{
|
|
89
|
-
_validateExecuteBySelf();
|
|
90
|
-
super.safeTransferFrom(from, to, id, value, data);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @notice Safe batch transfer; callable only by this contract via GuardController
|
|
95
|
-
* @param from Sender address
|
|
96
|
-
* @param to Recipient address
|
|
97
|
-
* @param ids Token type IDs
|
|
98
|
-
* @param values Amounts to transfer
|
|
99
|
-
* @param data Additional data for recipient hook
|
|
100
|
-
*/
|
|
101
|
-
function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data)
|
|
102
|
-
public
|
|
103
|
-
virtual
|
|
104
|
-
override(ERC1155Upgradeable, IERC1155)
|
|
105
|
-
{
|
|
106
|
-
_validateExecuteBySelf();
|
|
107
|
-
super.safeBatchTransferFrom(from, to, ids, values, data);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @notice Mint tokens to an account (callable only by this contract via GuardController)
|
|
112
|
-
* @param to Recipient address
|
|
113
|
-
* @param id Token type ID
|
|
114
|
-
* @param value Amount to mint
|
|
115
|
-
* @param data Additional data for recipient hook
|
|
116
|
-
*/
|
|
117
|
-
function mint(address to, uint256 id, uint256 value, bytes memory data) external virtual {
|
|
118
|
-
_validateExecuteBySelf();
|
|
119
|
-
_mint(to, id, value, data);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @notice Mint batch of tokens (callable only by this contract via GuardController)
|
|
124
|
-
* @param to Recipient address
|
|
125
|
-
* @param ids Token type IDs
|
|
126
|
-
* @param values Amounts to mint
|
|
127
|
-
* @param data Additional data for recipient hook
|
|
128
|
-
*/
|
|
129
|
-
function mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) external virtual {
|
|
130
|
-
_validateExecuteBySelf();
|
|
131
|
-
_mintBatch(to, ids, values, data);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* @notice Burn tokens from an account (callable only by this contract via GuardController)
|
|
136
|
-
* @param account Account to burn from
|
|
137
|
-
* @param id Token type ID
|
|
138
|
-
* @param value Amount to burn
|
|
139
|
-
*/
|
|
140
|
-
function burn(address account, uint256 id, uint256 value) public virtual override(ERC1155BurnableUpgradeable) {
|
|
141
|
-
_validateExecuteBySelf();
|
|
142
|
-
super.burn(account, id, value);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @notice Burn batch of tokens (callable only by this contract via GuardController)
|
|
147
|
-
* @param account Account to burn from
|
|
148
|
-
* @param ids Token type IDs
|
|
149
|
-
* @param values Amounts to burn
|
|
150
|
-
*/
|
|
151
|
-
function burnBatch(address account, uint256[] memory ids, uint256[] memory values)
|
|
152
|
-
public
|
|
153
|
-
virtual
|
|
154
|
-
override(ERC1155BurnableUpgradeable)
|
|
155
|
-
{
|
|
156
|
-
_validateExecuteBySelf();
|
|
157
|
-
super.burnBatch(account, ids, values);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function supportsInterface(bytes4 interfaceId)
|
|
161
|
-
public
|
|
162
|
-
view
|
|
163
|
-
virtual
|
|
164
|
-
override(ERC1155Upgradeable, SecureOwnable, RuntimeRBAC, GuardController, IERC165)
|
|
165
|
-
returns (bool)
|
|
166
|
-
{
|
|
167
|
-
return interfaceId == type(IERC1155).interfaceId || super.supportsInterface(interfaceId) || GuardController.supportsInterface(interfaceId);
|
|
168
|
-
}
|
|
169
|
-
}
|