@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,306 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// Copyright (c) 2025 Particle Crypto Security
|
|
3
|
-
pragma solidity 0.8.33;
|
|
4
|
-
|
|
5
|
-
// ============ IMPORTS ============
|
|
6
|
-
|
|
7
|
-
// Import core components (relative paths within protocol repo)
|
|
8
|
-
import "../execution/GuardController.sol";
|
|
9
|
-
import "../access/RuntimeRBAC.sol";
|
|
10
|
-
import "../security/SecureOwnable.sol";
|
|
11
|
-
import "../base/BaseStateMachine.sol";
|
|
12
|
-
import "../../utils/SharedValidation.sol";
|
|
13
|
-
import "../../interfaces/IDefinition.sol";
|
|
14
|
-
|
|
15
|
-
// ============ CONTRACT DOCUMENTATION ============
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @title BloxchainWallet
|
|
19
|
-
* @dev Official ParticleCS wallet controller built on Bloxchain Protocol
|
|
20
|
-
*
|
|
21
|
-
* This contract is based on the ControlBlox template and combines:
|
|
22
|
-
* - GuardController: Execution workflows and time-locked transactions
|
|
23
|
-
* - RuntimeRBAC: Runtime role creation and management
|
|
24
|
-
* - SecureOwnable: Secure ownership transfer and management
|
|
25
|
-
*
|
|
26
|
-
* It serves as the core on-chain controller for the Bloxchain Wallet application.
|
|
27
|
-
*/
|
|
28
|
-
contract BloxchainWallet is GuardController, RuntimeRBAC, SecureOwnable {
|
|
29
|
-
// ============ CONSTANTS ============
|
|
30
|
-
|
|
31
|
-
/// @notice Minimum time lock period: 1 day (86400 seconds)
|
|
32
|
-
uint256 public constant MIN_TIME_LOCK_PERIOD = 1 days;
|
|
33
|
-
|
|
34
|
-
/// @notice Maximum time lock period: 90 days (7776000 seconds)
|
|
35
|
-
uint256 public constant MAX_TIME_LOCK_PERIOD = 90 days;
|
|
36
|
-
|
|
37
|
-
/// @notice Maximum number of definition contracts allowed during initialization (prevents gas exhaustion and DoS)
|
|
38
|
-
/// @dev Limits external calls to untrusted contracts during initialization
|
|
39
|
-
uint256 public constant MAX_DEFINITION_CONTRACTS = 50;
|
|
40
|
-
|
|
41
|
-
/// @notice Maximum number of roles allowed during initialization (prevents gas exhaustion and DoS)
|
|
42
|
-
/// @dev Limits role creation during initialization to prevent excessive gas consumption
|
|
43
|
-
uint256 public constant MAX_INITIAL_ROLES = 50;
|
|
44
|
-
|
|
45
|
-
/// @notice Maximum schemas per definition contract (prevents gas griefing from unbounded getFunctionSchemas())
|
|
46
|
-
uint256 public constant MAX_SCHEMAS_PER_DEFINITION = 100;
|
|
47
|
-
|
|
48
|
-
/// @notice Maximum permissions per definition contract (prevents gas griefing from unbounded getRolePermissions())
|
|
49
|
-
uint256 public constant MAX_PERMISSIONS_PER_DEFINITION = 200;
|
|
50
|
-
|
|
51
|
-
// ============ CUSTOM ERRORS ============
|
|
52
|
-
|
|
53
|
-
/// @dev Thrown when the same definition contract address appears more than once in the initialization array
|
|
54
|
-
// error DuplicateDefinitionContract(address definition);
|
|
55
|
-
|
|
56
|
-
/// @dev Thrown when an address does not implement the IDefinition interface (ERC165)
|
|
57
|
-
error DefinitionNotIDefinition(address definition);
|
|
58
|
-
|
|
59
|
-
// ============ STRUCTS ============
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @dev Struct to hold role configuration data for initialization
|
|
63
|
-
* @param roleName The name of the role (must be unique, non-empty)
|
|
64
|
-
* @param maxWallets Maximum number of wallets allowed for this role (must be > 0)
|
|
65
|
-
* @notice Function permissions are NOT included here - they must be added via definition contracts
|
|
66
|
-
* @notice This ensures function schemas exist before permissions are assigned to roles
|
|
67
|
-
* @notice Permissions should be added via definition contracts after roles are created
|
|
68
|
-
*/
|
|
69
|
-
struct RoleConfig {
|
|
70
|
-
string roleName;
|
|
71
|
-
uint256 maxWallets;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ============ EVENTS ============
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* @dev Emitted when ETH is deposited to the wallet
|
|
78
|
-
* @param from The address that deposited the ETH
|
|
79
|
-
* @param amount The amount of ETH deposited
|
|
80
|
-
*/
|
|
81
|
-
event EthReceived(address indexed from, uint256 amount);
|
|
82
|
-
|
|
83
|
-
// ============ INITIALIZATION FUNCTIONS ============
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @notice Initializer to configure the BloxchainWallet
|
|
87
|
-
* @param initialOwner The initial owner address
|
|
88
|
-
* @param broadcaster The broadcaster address
|
|
89
|
-
* @param recovery The recovery address
|
|
90
|
-
* @param timeLockPeriodSec The timelock period in seconds
|
|
91
|
-
* @param eventForwarder The event forwarder address (optional)
|
|
92
|
-
* @dev For proxy/clone deployments, the deployer should call in the same transaction as deployment.
|
|
93
|
-
*/
|
|
94
|
-
function initialize(
|
|
95
|
-
address initialOwner,
|
|
96
|
-
address broadcaster,
|
|
97
|
-
address recovery,
|
|
98
|
-
uint256 timeLockPeriodSec,
|
|
99
|
-
address eventForwarder
|
|
100
|
-
)
|
|
101
|
-
public
|
|
102
|
-
virtual
|
|
103
|
-
override(GuardController, RuntimeRBAC, SecureOwnable)
|
|
104
|
-
initializer
|
|
105
|
-
{
|
|
106
|
-
_initializeBase(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* @notice Extended initializer with custom roles and definition contracts
|
|
111
|
-
* @param initialOwner The initial owner address
|
|
112
|
-
* @param broadcaster The broadcaster address
|
|
113
|
-
* @param recovery The recovery address
|
|
114
|
-
* @param timeLockPeriodSec The timelock period in seconds
|
|
115
|
-
* @param eventForwarder The event forwarder address (optional)
|
|
116
|
-
* @param roles Array of role configurations to create before loading definitions
|
|
117
|
-
* @param definitionContracts Array of definition contract addresses implementing IDefinition
|
|
118
|
-
* @dev Execution order:
|
|
119
|
-
* 1. Initialize base (loads RuntimeRBACDefinitions schemas and protected roles)
|
|
120
|
-
* 2. Create custom roles (roles are created with isProtected=false)
|
|
121
|
-
* 3. Load custom definitions (schemas first, then permissions added to existing roles)
|
|
122
|
-
* @dev All validation (protected schemas, duplicates, bounded sizes) is handled internally
|
|
123
|
-
* @custom:security-intentional No caller restriction: designed for clone-based factory initialization where the factory creates the clone and calls this initializer in the same transaction. The factory (or deployer) is the only caller; no window exists for front-running. Do not deploy instances without initializing atomically in the same transaction.
|
|
124
|
-
*/
|
|
125
|
-
function initializeWithRolesAndDefinitions(
|
|
126
|
-
address initialOwner,
|
|
127
|
-
address broadcaster,
|
|
128
|
-
address recovery,
|
|
129
|
-
uint256 timeLockPeriodSec,
|
|
130
|
-
address eventForwarder,
|
|
131
|
-
RoleConfig[] memory roles,
|
|
132
|
-
IDefinition[] memory definitionContracts
|
|
133
|
-
) public initializer {
|
|
134
|
-
// Initialize base (validates time lock period and initializes parent contracts)
|
|
135
|
-
// This also loads RuntimeRBACDefinitions schemas and creates protected roles (OWNER, BROADCASTER, RECOVERY)
|
|
136
|
-
_initializeBase(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
137
|
-
|
|
138
|
-
// Validate roles array length to prevent gas exhaustion and DoS attacks
|
|
139
|
-
if (roles.length > MAX_INITIAL_ROLES) {
|
|
140
|
-
revert SharedValidation.BatchSizeExceeded(roles.length, MAX_INITIAL_ROLES);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Create custom roles before loading definitions
|
|
144
|
-
for (uint256 i = 0; i < roles.length; i++) {
|
|
145
|
-
_createRole(roles[i].roleName, roles[i].maxWallets, false);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Validate definition contracts array length
|
|
149
|
-
if (definitionContracts.length > MAX_DEFINITION_CONTRACTS) {
|
|
150
|
-
revert SharedValidation.BatchSizeExceeded(definitionContracts.length, MAX_DEFINITION_CONTRACTS);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Load custom definitions from each definition contract (no duplicates, bounded sizes, allowProtectedSchemas=false)
|
|
154
|
-
for (uint256 i = 0; i < definitionContracts.length; i++) {
|
|
155
|
-
address def = address(definitionContracts[i]);
|
|
156
|
-
// SharedValidation.validateNotZeroAddress(def);
|
|
157
|
-
|
|
158
|
-
// Reject duplicate definition contract addresses
|
|
159
|
-
// note: this check and error can be removed as the protocol will handle duplicates
|
|
160
|
-
// for (uint256 j = 0; j < i; j++) {
|
|
161
|
-
// if (address(definitionContracts[j]) == def) revert DuplicateDefinitionContract(def);
|
|
162
|
-
// }
|
|
163
|
-
|
|
164
|
-
// This will be applicable in the next bloxchain update
|
|
165
|
-
// Require ERC165 IDefinition support for clearer errors and safety
|
|
166
|
-
if (!definitionContracts[i].supportsInterface(type(IDefinition).interfaceId)) {
|
|
167
|
-
revert DefinitionNotIDefinition(def);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
EngineBlox.FunctionSchema[] memory schemas = definitionContracts[i].getFunctionSchemas();
|
|
171
|
-
IDefinition.RolePermission memory permissions = definitionContracts[i].getRolePermissions();
|
|
172
|
-
|
|
173
|
-
if (schemas.length > MAX_SCHEMAS_PER_DEFINITION) {
|
|
174
|
-
revert SharedValidation.BatchSizeExceeded(schemas.length, MAX_SCHEMAS_PER_DEFINITION);
|
|
175
|
-
}
|
|
176
|
-
if (permissions.roleHashes.length > MAX_PERMISSIONS_PER_DEFINITION) {
|
|
177
|
-
revert SharedValidation.BatchSizeExceeded(permissions.roleHashes.length, MAX_PERMISSIONS_PER_DEFINITION);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// When using protocol version with allowProtectedSchemas parameter, pass false for custom definitions
|
|
181
|
-
_loadDefinitions(
|
|
182
|
-
schemas,
|
|
183
|
-
permissions.roleHashes,
|
|
184
|
-
permissions.functionPermissions,
|
|
185
|
-
false // Custom definitions must not be protected
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
// This will be applicable in the next bloxchain update
|
|
189
|
-
// _loadDefinitions(
|
|
190
|
-
// schemas,
|
|
191
|
-
// permissions.roleHashes,
|
|
192
|
-
// permissions.functionPermissions,
|
|
193
|
-
// false // Custom definitions must not be protected
|
|
194
|
-
// );
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// ============ DEPOSIT & INTERFACE FUNCTIONS ============
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* @dev Explicit deposit function for ETH deposits
|
|
202
|
-
* @notice Users must call this function to deposit ETH to the wallet controller
|
|
203
|
-
* @notice Direct ETH transfers to the contract will revert (receive/fallback revert)
|
|
204
|
-
* @notice ETH can still be forced in without calling deposit() (e.g. selfdestruct); such balance will not emit EthReceived
|
|
205
|
-
*/
|
|
206
|
-
function deposit() external payable {
|
|
207
|
-
emit EthReceived(msg.sender, msg.value);
|
|
208
|
-
// ETH is automatically added to contract balance
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* @dev See {IERC165-supportsInterface}.
|
|
213
|
-
*/
|
|
214
|
-
function supportsInterface(bytes4 interfaceId)
|
|
215
|
-
public
|
|
216
|
-
view
|
|
217
|
-
virtual
|
|
218
|
-
override(GuardController, RuntimeRBAC, SecureOwnable)
|
|
219
|
-
returns (bool)
|
|
220
|
-
{
|
|
221
|
-
return
|
|
222
|
-
GuardController.supportsInterface(interfaceId) ||
|
|
223
|
-
RuntimeRBAC.supportsInterface(interfaceId) ||
|
|
224
|
-
SecureOwnable.supportsInterface(interfaceId);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// ============ FALLBACK & RECEIVE FUNCTIONS ============
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* @dev Fallback function to reject accidental calls
|
|
231
|
-
* @notice Prevents accidental ETH transfers and unknown function calls
|
|
232
|
-
* @notice Users must use deposit() function to send ETH
|
|
233
|
-
*/
|
|
234
|
-
fallback() external payable {
|
|
235
|
-
revert SharedValidation.NotSupported();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* @dev Receive function to reject direct ETH transfers
|
|
240
|
-
* @notice Prevents accidental ETH transfers
|
|
241
|
-
* @notice Users must use deposit() function to send ETH
|
|
242
|
-
*/
|
|
243
|
-
receive() external payable {
|
|
244
|
-
revert SharedValidation.NotSupported();
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// ============ OVERRIDE FUNCTIONS ============
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* @dev Override to resolve ambiguity between BaseStateMachine and SecureOwnable
|
|
251
|
-
* @param newTimeLockPeriodSec The new time lock period in seconds
|
|
252
|
-
* @notice Validates that the new time lock period is between MIN_TIME_LOCK_PERIOD and MAX_TIME_LOCK_PERIOD
|
|
253
|
-
*/
|
|
254
|
-
function _updateTimeLockPeriod(uint256 newTimeLockPeriodSec)
|
|
255
|
-
internal
|
|
256
|
-
virtual
|
|
257
|
-
override(BaseStateMachine, SecureOwnable)
|
|
258
|
-
{
|
|
259
|
-
_validateTimeLockPeriod(newTimeLockPeriodSec);
|
|
260
|
-
SecureOwnable._updateTimeLockPeriod(newTimeLockPeriodSec);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// ============ INTERNAL FUNCTIONS ============
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* @dev Internal function to initialize base state (common to all initialization paths)
|
|
267
|
-
* @param initialOwner The initial owner address
|
|
268
|
-
* @param broadcaster The broadcaster address
|
|
269
|
-
* @param recovery The recovery address
|
|
270
|
-
* @param timeLockPeriodSec The timelock period in seconds
|
|
271
|
-
* @param eventForwarder The event forwarder address (optional)
|
|
272
|
-
* @notice Validates time lock period and initializes all parent contracts
|
|
273
|
-
* @notice The guarded initialization ensures BaseStateMachine is only initialized once
|
|
274
|
-
*/
|
|
275
|
-
function _initializeBase(
|
|
276
|
-
address initialOwner,
|
|
277
|
-
address broadcaster,
|
|
278
|
-
address recovery,
|
|
279
|
-
uint256 timeLockPeriodSec,
|
|
280
|
-
address eventForwarder
|
|
281
|
-
) internal {
|
|
282
|
-
// Validate time lock period before initialization
|
|
283
|
-
_validateTimeLockPeriod(timeLockPeriodSec);
|
|
284
|
-
|
|
285
|
-
// Initialize all parent contracts.
|
|
286
|
-
// The guarded initialization ensures BaseStateMachine is only initialized once.
|
|
287
|
-
GuardController.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
288
|
-
RuntimeRBAC.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
289
|
-
SecureOwnable.initialize(initialOwner, broadcaster, recovery, timeLockPeriodSec, eventForwarder);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* @dev Validates that a time lock period is within the allowed range
|
|
294
|
-
* @param timeLockPeriodSec The time lock period in seconds to validate
|
|
295
|
-
* @notice Reverts with InvalidTimeLockPeriod if the period is outside MIN_TIME_LOCK_PERIOD and MAX_TIME_LOCK_PERIOD
|
|
296
|
-
*/
|
|
297
|
-
function _validateTimeLockPeriod(uint256 timeLockPeriodSec) internal pure {
|
|
298
|
-
if (
|
|
299
|
-
timeLockPeriodSec < MIN_TIME_LOCK_PERIOD ||
|
|
300
|
-
timeLockPeriodSec > MAX_TIME_LOCK_PERIOD
|
|
301
|
-
) {
|
|
302
|
-
revert SharedValidation.InvalidTimeLockPeriod(timeLockPeriodSec);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.33;
|
|
3
|
-
|
|
4
|
-
// OpenZeppelin
|
|
5
|
-
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
|
|
6
|
-
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
|
|
7
|
-
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
8
|
-
|
|
9
|
-
// Core
|
|
10
|
-
import "../../security/SecureOwnable.sol";
|
|
11
|
-
import "../../access/RuntimeRBAC.sol";
|
|
12
|
-
import "../../execution/GuardController.sol";
|
|
13
|
-
import "../../base/BaseStateMachine.sol";
|
|
14
|
-
import "../../../utils/SharedValidation.sol";
|
|
15
|
-
import "../../../interfaces/IDefinition.sol";
|
|
16
|
-
import "./lib/definitions/ERC20BloxDefinitions.sol";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @title ERC20Blox
|
|
20
|
-
* @dev ERC20 token (IERC20) with SecureOwnable, RuntimeRBAC, and GuardController.
|
|
21
|
-
* Exposes transfer (ERC20), mint (owner-only), and burn (ERC20Burnable).
|
|
22
|
-
* @custom:security-contact security@particlecrypto.com
|
|
23
|
-
*/
|
|
24
|
-
contract ERC20Blox is
|
|
25
|
-
IERC20,
|
|
26
|
-
ERC20Upgradeable,
|
|
27
|
-
ERC20BurnableUpgradeable,
|
|
28
|
-
SecureOwnable,
|
|
29
|
-
RuntimeRBAC,
|
|
30
|
-
GuardController
|
|
31
|
-
{
|
|
32
|
-
using SharedValidation for *;
|
|
33
|
-
|
|
34
|
-
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
35
|
-
constructor() {
|
|
36
|
-
_disableInitializers();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @dev Override to resolve diamond: SecureOwnable, RuntimeRBAC, GuardController all define initialize(5 params).
|
|
41
|
-
* Call this first, then initializeToken(name, symbol) to set ERC20 metadata.
|
|
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) initializer {
|
|
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
|
-
// Load ERC20Blox execution selectors (transfer, transferFrom, mint, burn, burnFrom) so controller can execute them
|
|
55
|
-
IDefinition.RolePermission memory erc20Permissions = ERC20BloxDefinitions.getRolePermissions();
|
|
56
|
-
_loadDefinitions(
|
|
57
|
-
ERC20BloxDefinitions.getFunctionSchemas(),
|
|
58
|
-
erc20Permissions.roleHashes,
|
|
59
|
-
erc20Permissions.functionPermissions,
|
|
60
|
-
true
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
// Register ERC20Blox system macro selectors (allowed to target address(this) for time-lock/meta-tx execution)
|
|
64
|
-
_addMacroSelector(ERC20BloxDefinitions.TRANSFER_SELECTOR);
|
|
65
|
-
_addMacroSelector(ERC20BloxDefinitions.TRANSFER_FROM_SELECTOR);
|
|
66
|
-
_addMacroSelector(ERC20BloxDefinitions.MINT_SELECTOR);
|
|
67
|
-
_addMacroSelector(ERC20BloxDefinitions.BURN_SELECTOR);
|
|
68
|
-
_addMacroSelector(ERC20BloxDefinitions.BURN_FROM_SELECTOR);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @notice Initialize the ERC20 token name and symbol. Call after initialize(5 params).
|
|
73
|
-
* @param name Token name
|
|
74
|
-
* @param symbol Token symbol
|
|
75
|
-
*/
|
|
76
|
-
function initializeToken(string memory name, string memory symbol) public reinitializer(2) {
|
|
77
|
-
__ERC20_init(name, symbol);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @dev Override to resolve ambiguity between BaseStateMachine and SecureOwnable.
|
|
82
|
-
*/
|
|
83
|
-
function _updateTimeLockPeriod(uint256 newTimeLockPeriodSec) internal virtual override(BaseStateMachine, SecureOwnable) {
|
|
84
|
-
SecureOwnable._updateTimeLockPeriod(newTimeLockPeriodSec);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @notice Transfer tokens to an account (callable only by this contract via GuardController)
|
|
89
|
-
* @param to Recipient address
|
|
90
|
-
* @param value Amount to transfer
|
|
91
|
-
*/
|
|
92
|
-
function transfer(address to, uint256 value) public virtual override(ERC20Upgradeable, IERC20) returns (bool) {
|
|
93
|
-
SharedValidation.validateInternalCall(address(this));
|
|
94
|
-
return super.transfer(to, value);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @notice Transfer tokens from one account to another (with allowance); callable only by this contract via GuardController
|
|
99
|
-
* @param from Sender address
|
|
100
|
-
* @param to Recipient address
|
|
101
|
-
* @param value Amount to transfer
|
|
102
|
-
*/
|
|
103
|
-
function transferFrom(address from, address to, uint256 value) public virtual override(ERC20Upgradeable, IERC20) returns (bool) {
|
|
104
|
-
SharedValidation.validateInternalCall(address(this));
|
|
105
|
-
return super.transferFrom(from, to, value);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @notice Mint tokens to an account (callable only by this contract via GuardController)
|
|
110
|
-
* @param to Recipient address
|
|
111
|
-
* @param amount Amount to mint
|
|
112
|
-
*/
|
|
113
|
-
function mint(address to, uint256 amount) external virtual {
|
|
114
|
-
SharedValidation.validateInternalCall(address(this));
|
|
115
|
-
_mint(to, amount);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @notice Burn tokens from caller (callable only by this contract via GuardController)
|
|
120
|
-
* @param value Amount to burn
|
|
121
|
-
*/
|
|
122
|
-
function burn(uint256 value) public virtual override(ERC20BurnableUpgradeable) {
|
|
123
|
-
SharedValidation.validateInternalCall(address(this));
|
|
124
|
-
super.burn(value);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* @notice Burn tokens from an account (with allowance); callable only by this contract via GuardController
|
|
129
|
-
* @param account Account to burn from
|
|
130
|
-
* @param value Amount to burn
|
|
131
|
-
*/
|
|
132
|
-
function burnFrom(address account, uint256 value) public virtual override(ERC20BurnableUpgradeable) {
|
|
133
|
-
SharedValidation.validateInternalCall(address(this));
|
|
134
|
-
super.burnFrom(account, value);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function supportsInterface(bytes4 interfaceId) public view virtual override(SecureOwnable, RuntimeRBAC, GuardController) returns (bool) {
|
|
138
|
-
return interfaceId == type(IERC20).interfaceId || GuardController.supportsInterface(interfaceId);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
pragma solidity 0.8.33;
|
|
3
|
-
|
|
4
|
-
import "../../../../lib/EngineBlox.sol";
|
|
5
|
-
import "../../../../../interfaces/IDefinition.sol";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @title ERC20BloxDefinitions
|
|
9
|
-
* @dev Definition library for ERC20Blox execution selectors (transfer, transferFrom, mint, burn, burnFrom).
|
|
10
|
-
* Registers function schemas and role permissions so the GuardController can execute these functions
|
|
11
|
-
* via time-lock and meta-transaction workflows. Handler permissions (executeWithTimeLock, etc.) are
|
|
12
|
-
* defined in GuardControllerDefinitions.
|
|
13
|
-
* @custom:security-contact security@particlecrypto.com
|
|
14
|
-
*/
|
|
15
|
-
library ERC20BloxDefinitions {
|
|
16
|
-
|
|
17
|
-
// System macro selectors (allowed to target address(this) for GuardController execution)
|
|
18
|
-
bytes4 public constant TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
|
|
19
|
-
bytes4 public constant TRANSFER_FROM_SELECTOR = bytes4(keccak256("transferFrom(address,address,uint256)"));
|
|
20
|
-
bytes4 public constant MINT_SELECTOR = bytes4(keccak256("mint(address,uint256)"));
|
|
21
|
-
bytes4 public constant BURN_SELECTOR = bytes4(keccak256("burn(uint256)"));
|
|
22
|
-
bytes4 public constant BURN_FROM_SELECTOR = bytes4(keccak256("burnFrom(address,uint256)"));
|
|
23
|
-
|
|
24
|
-
bytes32 public constant ERC20_OPERATION = keccak256("ERC20_OPERATION");
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @dev Returns function schemas for ERC20Blox execution selectors (used by controller).
|
|
28
|
-
*/
|
|
29
|
-
function getFunctionSchemas() public pure returns (EngineBlox.FunctionSchema[] memory) {
|
|
30
|
-
EngineBlox.FunctionSchema[] memory schemas = new EngineBlox.FunctionSchema[](5);
|
|
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 transferHandlers = new bytes4[](1);
|
|
56
|
-
transferHandlers[0] = TRANSFER_SELECTOR;
|
|
57
|
-
bytes4[] memory transferFromHandlers = new bytes4[](1);
|
|
58
|
-
transferFromHandlers[0] = TRANSFER_FROM_SELECTOR;
|
|
59
|
-
bytes4[] memory mintHandlers = new bytes4[](1);
|
|
60
|
-
mintHandlers[0] = MINT_SELECTOR;
|
|
61
|
-
bytes4[] memory burnHandlers = new bytes4[](1);
|
|
62
|
-
burnHandlers[0] = BURN_SELECTOR;
|
|
63
|
-
bytes4[] memory burnFromHandlers = new bytes4[](1);
|
|
64
|
-
burnFromHandlers[0] = BURN_FROM_SELECTOR;
|
|
65
|
-
|
|
66
|
-
schemas[0] = EngineBlox.FunctionSchema({
|
|
67
|
-
functionSignature: "transfer(address,uint256)",
|
|
68
|
-
functionSelector: TRANSFER_SELECTOR,
|
|
69
|
-
operationType: ERC20_OPERATION,
|
|
70
|
-
operationName: "ERC20_TRANSFER",
|
|
71
|
-
supportedActionsBitmap: actionsBitmap,
|
|
72
|
-
isProtected: true,
|
|
73
|
-
handlerForSelectors: transferHandlers
|
|
74
|
-
});
|
|
75
|
-
schemas[1] = EngineBlox.FunctionSchema({
|
|
76
|
-
functionSignature: "transferFrom(address,address,uint256)",
|
|
77
|
-
functionSelector: TRANSFER_FROM_SELECTOR,
|
|
78
|
-
operationType: ERC20_OPERATION,
|
|
79
|
-
operationName: "ERC20_TRANSFER_FROM",
|
|
80
|
-
supportedActionsBitmap: actionsBitmap,
|
|
81
|
-
isProtected: true,
|
|
82
|
-
handlerForSelectors: transferFromHandlers
|
|
83
|
-
});
|
|
84
|
-
schemas[2] = EngineBlox.FunctionSchema({
|
|
85
|
-
functionSignature: "mint(address,uint256)",
|
|
86
|
-
functionSelector: MINT_SELECTOR,
|
|
87
|
-
operationType: ERC20_OPERATION,
|
|
88
|
-
operationName: "ERC20_MINT",
|
|
89
|
-
supportedActionsBitmap: actionsBitmap,
|
|
90
|
-
isProtected: true,
|
|
91
|
-
handlerForSelectors: mintHandlers
|
|
92
|
-
});
|
|
93
|
-
schemas[3] = EngineBlox.FunctionSchema({
|
|
94
|
-
functionSignature: "burn(uint256)",
|
|
95
|
-
functionSelector: BURN_SELECTOR,
|
|
96
|
-
operationType: ERC20_OPERATION,
|
|
97
|
-
operationName: "ERC20_BURN",
|
|
98
|
-
supportedActionsBitmap: actionsBitmap,
|
|
99
|
-
isProtected: true,
|
|
100
|
-
handlerForSelectors: burnHandlers
|
|
101
|
-
});
|
|
102
|
-
schemas[4] = EngineBlox.FunctionSchema({
|
|
103
|
-
functionSignature: "burnFrom(address,uint256)",
|
|
104
|
-
functionSelector: BURN_FROM_SELECTOR,
|
|
105
|
-
operationType: ERC20_OPERATION,
|
|
106
|
-
operationName: "ERC20_BURN_FROM",
|
|
107
|
-
supportedActionsBitmap: actionsBitmap,
|
|
108
|
-
isProtected: true,
|
|
109
|
-
handlerForSelectors: burnFromHandlers
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return schemas;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* @dev Returns role permissions for ERC20Blox execution selectors (OWNER and BROADCASTER).
|
|
117
|
-
*/
|
|
118
|
-
function getRolePermissions() public pure returns (IDefinition.RolePermission memory) {
|
|
119
|
-
bytes32[] memory roleHashes = new bytes32[](10);
|
|
120
|
-
EngineBlox.FunctionPermission[] memory functionPermissions = new EngineBlox.FunctionPermission[](10);
|
|
121
|
-
|
|
122
|
-
EngineBlox.TxAction[] memory ownerTimeLockRequest = new EngineBlox.TxAction[](1);
|
|
123
|
-
ownerTimeLockRequest[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_REQUEST;
|
|
124
|
-
EngineBlox.TxAction[] memory ownerTimeLockApprove = new EngineBlox.TxAction[](1);
|
|
125
|
-
ownerTimeLockApprove[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_APPROVE;
|
|
126
|
-
EngineBlox.TxAction[] memory ownerTimeLockCancel = new EngineBlox.TxAction[](1);
|
|
127
|
-
ownerTimeLockCancel[0] = EngineBlox.TxAction.EXECUTE_TIME_DELAY_CANCEL;
|
|
128
|
-
EngineBlox.TxAction[] memory ownerMetaSign = new EngineBlox.TxAction[](1);
|
|
129
|
-
ownerMetaSign[0] = EngineBlox.TxAction.SIGN_META_REQUEST_AND_APPROVE;
|
|
130
|
-
EngineBlox.TxAction[] memory ownerMetaApprove = new EngineBlox.TxAction[](1);
|
|
131
|
-
ownerMetaApprove[0] = EngineBlox.TxAction.SIGN_META_APPROVE;
|
|
132
|
-
EngineBlox.TxAction[] memory ownerMetaCancel = new EngineBlox.TxAction[](1);
|
|
133
|
-
ownerMetaCancel[0] = EngineBlox.TxAction.SIGN_META_CANCEL;
|
|
134
|
-
EngineBlox.TxAction[] memory broadcasterMetaExec = new EngineBlox.TxAction[](1);
|
|
135
|
-
broadcasterMetaExec[0] = EngineBlox.TxAction.EXECUTE_META_REQUEST_AND_APPROVE;
|
|
136
|
-
EngineBlox.TxAction[] memory broadcasterMetaApprove = new EngineBlox.TxAction[](1);
|
|
137
|
-
broadcasterMetaApprove[0] = EngineBlox.TxAction.EXECUTE_META_APPROVE;
|
|
138
|
-
EngineBlox.TxAction[] memory broadcasterMetaCancel = new EngineBlox.TxAction[](1);
|
|
139
|
-
broadcasterMetaCancel[0] = EngineBlox.TxAction.EXECUTE_META_CANCEL;
|
|
140
|
-
|
|
141
|
-
uint16 ownerBitmap = EngineBlox.createBitmapFromActions(ownerTimeLockRequest)
|
|
142
|
-
| EngineBlox.createBitmapFromActions(ownerTimeLockApprove)
|
|
143
|
-
| EngineBlox.createBitmapFromActions(ownerTimeLockCancel)
|
|
144
|
-
| EngineBlox.createBitmapFromActions(ownerMetaSign)
|
|
145
|
-
| EngineBlox.createBitmapFromActions(ownerMetaApprove)
|
|
146
|
-
| EngineBlox.createBitmapFromActions(ownerMetaCancel);
|
|
147
|
-
uint16 broadcasterBitmap = EngineBlox.createBitmapFromActions(broadcasterMetaExec)
|
|
148
|
-
| EngineBlox.createBitmapFromActions(broadcasterMetaApprove)
|
|
149
|
-
| EngineBlox.createBitmapFromActions(broadcasterMetaCancel);
|
|
150
|
-
|
|
151
|
-
bytes4[5] memory selectors = [TRANSFER_SELECTOR, TRANSFER_FROM_SELECTOR, MINT_SELECTOR, BURN_SELECTOR, BURN_FROM_SELECTOR];
|
|
152
|
-
for (uint256 i = 0; i < 5; i++) {
|
|
153
|
-
bytes4[] memory selfRef = new bytes4[](1);
|
|
154
|
-
selfRef[0] = selectors[i];
|
|
155
|
-
roleHashes[i] = EngineBlox.OWNER_ROLE;
|
|
156
|
-
functionPermissions[i] = EngineBlox.FunctionPermission({
|
|
157
|
-
functionSelector: selectors[i],
|
|
158
|
-
grantedActionsBitmap: ownerBitmap,
|
|
159
|
-
handlerForSelectors: selfRef
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
for (uint256 i = 0; i < 5; i++) {
|
|
163
|
-
bytes4[] memory selfRef = new bytes4[](1);
|
|
164
|
-
selfRef[0] = selectors[i];
|
|
165
|
-
roleHashes[5 + i] = EngineBlox.BROADCASTER_ROLE;
|
|
166
|
-
functionPermissions[5 + i] = EngineBlox.FunctionPermission({
|
|
167
|
-
functionSelector: selectors[i],
|
|
168
|
-
grantedActionsBitmap: broadcasterBitmap,
|
|
169
|
-
handlerForSelectors: selfRef
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return IDefinition.RolePermission({
|
|
174
|
-
roleHashes: roleHashes,
|
|
175
|
-
functionPermissions: functionPermissions
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* @dev ERC165: report support for IDefinition when this library is used at an address
|
|
181
|
-
*/
|
|
182
|
-
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
|
|
183
|
-
return interfaceId == type(IDefinition).interfaceId;
|
|
184
|
-
}
|
|
185
|
-
}
|