zk-agent-cli 0.1.0-beta.1 → 0.1.0-beta.3

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 (31) hide show
  1. package/README.md +23 -8
  2. package/dist/builtin-account-profiles/artifacts/daily-spend-limit/Account.json +693 -0
  3. package/dist/builtin-account-profiles/artifacts/sed-lite/Account.json +970 -0
  4. package/dist/builtin-account-profiles/artifacts/sed-lite/EOAValidator.json +50 -0
  5. package/dist/builtin-account-profiles/artifacts/sed-lite/NativePerTxLimitHook.json +267 -0
  6. package/dist/builtin-account-profiles/artifacts/sed-lite/TargetAllowlistHook.json +346 -0
  7. package/dist/builtin-account-profiles/artifacts/sed-lite/TargetSelectorAllowlistHook.json +643 -0
  8. package/dist/builtin-account-profiles/contracts/daily-spend-limit/AAFactory.sol +28 -0
  9. package/dist/builtin-account-profiles/contracts/daily-spend-limit/Account.sol +179 -0
  10. package/dist/builtin-account-profiles/contracts/daily-spend-limit/SpendLimit.sol +85 -0
  11. package/dist/builtin-account-profiles/contracts/sed-lite/Account.sol +230 -0
  12. package/dist/builtin-account-profiles/contracts/sed-lite/Auth.sol +16 -0
  13. package/dist/builtin-account-profiles/contracts/sed-lite/BootloaderAuth.sol +11 -0
  14. package/dist/builtin-account-profiles/contracts/sed-lite/EOAValidator.sol +23 -0
  15. package/dist/builtin-account-profiles/contracts/sed-lite/IValidationHook.sol +20 -0
  16. package/dist/builtin-account-profiles/contracts/sed-lite/IValidator.sol +11 -0
  17. package/dist/builtin-account-profiles/contracts/sed-lite/ModuleAuth.sol +11 -0
  18. package/dist/builtin-account-profiles/contracts/sed-lite/ModuleManager.sol +46 -0
  19. package/dist/builtin-account-profiles/contracts/sed-lite/NativePerTxLimitHook.sol +67 -0
  20. package/dist/builtin-account-profiles/contracts/sed-lite/OwnerManager.sol +25 -0
  21. package/dist/builtin-account-profiles/contracts/sed-lite/SelfAuth.sol +9 -0
  22. package/dist/builtin-account-profiles/contracts/sed-lite/TargetAllowlistHook.sol +110 -0
  23. package/dist/builtin-account-profiles/contracts/sed-lite/TargetSelectorAllowlistHook.sol +263 -0
  24. package/dist/builtin-account-profiles/contracts/sed-lite/ValidationHookManager.sol +76 -0
  25. package/dist/builtin-account-profiles/contracts/sed-lite/ValidatorManager.sol +31 -0
  26. package/dist/builtin-account-profiles/package.json +5 -0
  27. package/dist/connector-ui/assets/index-BnFLonFL.css +1 -0
  28. package/dist/connector-ui/assets/index-WTJRR5fK.js +40 -0
  29. package/dist/connector-ui/index.html +13 -0
  30. package/dist/index.js +248 -26
  31. package/package.json +1 -1
@@ -0,0 +1,67 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import '@matterlabs/zksync-contracts/contracts/system-contracts/libraries/TransactionHelper.sol';
5
+ import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
6
+ import './IValidationHook.sol';
7
+
8
+ contract NativePerTxLimitHook is ERC165, IValidationHook {
9
+ struct LimitState {
10
+ uint256 maxPerTx;
11
+ bool enabled;
12
+ }
13
+
14
+ mapping(address => LimitState) public limits;
15
+
16
+ event MaxPerTxSet(address indexed account, uint256 maxPerTx);
17
+ event MaxPerTxRemoved(address indexed account);
18
+
19
+ function init(bytes calldata initData) external override {
20
+ uint256 maxPerTx = abi.decode(initData, (uint256));
21
+ _setLimit(msg.sender, maxPerTx);
22
+ emit Inited(msg.sender);
23
+ }
24
+
25
+ function disable() external override {
26
+ delete limits[msg.sender];
27
+ emit Disabled(msg.sender);
28
+ }
29
+
30
+ function isInited(address account) external view override returns (bool) {
31
+ return limits[account].enabled;
32
+ }
33
+
34
+ function setMaxPerTx(uint256 maxPerTx) external {
35
+ _setLimit(msg.sender, maxPerTx);
36
+ }
37
+
38
+ function removeMaxPerTx() external {
39
+ require(limits[msg.sender].enabled, 'Limit hook is not enabled');
40
+ delete limits[msg.sender];
41
+ emit MaxPerTxRemoved(msg.sender);
42
+ }
43
+
44
+ function validationHook(bytes32, Transaction calldata transaction) external view override {
45
+ LimitState memory state = limits[msg.sender];
46
+ if (!state.enabled) {
47
+ return;
48
+ }
49
+
50
+ uint256 value = transaction.reserved[1];
51
+ if (value == 0) {
52
+ value = transaction.value;
53
+ }
54
+
55
+ require(value <= state.maxPerTx, 'Native transfer exceeds hook per-tx cap');
56
+ }
57
+
58
+ function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
59
+ return interfaceId == type(IValidationHook).interfaceId || super.supportsInterface(interfaceId);
60
+ }
61
+
62
+ function _setLimit(address account, uint256 maxPerTx) internal {
63
+ require(maxPerTx > 0, 'Spend cap must be greater than zero');
64
+ limits[account] = LimitState({ maxPerTx: maxPerTx, enabled: true });
65
+ emit MaxPerTxSet(account, maxPerTx);
66
+ }
67
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import './Auth.sol';
5
+
6
+ abstract contract OwnerManager is Auth {
7
+ address public owner;
8
+
9
+ event OwnerChanged(address indexed previousOwner, address indexed newOwner);
10
+
11
+ function changeOwner(address newOwner) external onlySelf {
12
+ _changeOwner(newOwner);
13
+ }
14
+
15
+ function _initializeOwner(address initialOwner) internal {
16
+ require(initialOwner != address(0), 'Owner must not be zero');
17
+ owner = initialOwner;
18
+ }
19
+
20
+ function _changeOwner(address newOwner) internal {
21
+ require(newOwner != address(0), 'Owner must not be zero');
22
+ emit OwnerChanged(owner, newOwner);
23
+ owner = newOwner;
24
+ }
25
+ }
@@ -0,0 +1,9 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ abstract contract SelfAuth {
5
+ modifier onlySelf() {
6
+ require(msg.sender == address(this), 'Only the account contract can call this method');
7
+ _;
8
+ }
9
+ }
@@ -0,0 +1,110 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import '@matterlabs/zksync-contracts/contracts/system-contracts/libraries/TransactionHelper.sol';
5
+ import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
6
+ import './IValidationHook.sol';
7
+
8
+ contract TargetAllowlistHook is ERC165, IValidationHook {
9
+ mapping(address => bool) public enabled;
10
+ mapping(address => mapping(address => bool)) public allowedTargets;
11
+ mapping(address => address[]) private targetLists;
12
+
13
+ event AllowedTargetAdded(address indexed account, address indexed target);
14
+ event AllowedTargetRemoved(address indexed account, address indexed target);
15
+
16
+ function init(bytes calldata initData) external override {
17
+ address[] memory targets = abi.decode(initData, (address[]));
18
+ enabled[msg.sender] = true;
19
+
20
+ uint256 length = targets.length;
21
+ for (uint256 i = 0; i < length; i += 1) {
22
+ _addAllowedTarget(msg.sender, targets[i]);
23
+ }
24
+
25
+ emit Inited(msg.sender);
26
+ }
27
+
28
+ function disable() external override {
29
+ require(enabled[msg.sender], 'Allowlist hook is not enabled');
30
+ _clearAllowedTargets(msg.sender);
31
+ enabled[msg.sender] = false;
32
+ emit Disabled(msg.sender);
33
+ }
34
+
35
+ function isInited(address account) external view override returns (bool) {
36
+ return enabled[account];
37
+ }
38
+
39
+ function state(address account) external view returns (bool accountEnabled, address[] memory targets) {
40
+ return (enabled[account], targetLists[account]);
41
+ }
42
+
43
+ function isTargetAllowed(address account, address target) external view returns (bool) {
44
+ return allowedTargets[account][target];
45
+ }
46
+
47
+ function addAllowedTarget(address target) external {
48
+ require(enabled[msg.sender], 'Allowlist hook is not enabled');
49
+ _addAllowedTarget(msg.sender, target);
50
+ }
51
+
52
+ function removeAllowedTarget(address target) external {
53
+ require(enabled[msg.sender], 'Allowlist hook is not enabled');
54
+ require(allowedTargets[msg.sender][target], 'Target is not allowlisted');
55
+
56
+ delete allowedTargets[msg.sender][target];
57
+
58
+ address[] storage targets = targetLists[msg.sender];
59
+ uint256 length = targets.length;
60
+ for (uint256 i = 0; i < length; i += 1) {
61
+ if (targets[i] == target) {
62
+ uint256 lastIndex = length - 1;
63
+ if (i != lastIndex) {
64
+ targets[i] = targets[lastIndex];
65
+ }
66
+ targets.pop();
67
+ break;
68
+ }
69
+ }
70
+
71
+ emit AllowedTargetRemoved(msg.sender, target);
72
+ }
73
+
74
+ function validationHook(bytes32, Transaction calldata transaction) external view override {
75
+ if (!enabled[msg.sender]) {
76
+ return;
77
+ }
78
+
79
+ address target = address(uint160(transaction.to));
80
+ if (target == msg.sender) {
81
+ return;
82
+ }
83
+
84
+ require(allowedTargets[msg.sender][target], 'Target is not allowlisted');
85
+ }
86
+
87
+ function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
88
+ return interfaceId == type(IValidationHook).interfaceId || super.supportsInterface(interfaceId);
89
+ }
90
+
91
+ function _addAllowedTarget(address account, address target) internal {
92
+ require(target != address(0), 'Target must not be zero');
93
+ require(target != account, 'Account self-target is implicit');
94
+ require(!allowedTargets[account][target], 'Target already allowlisted');
95
+
96
+ allowedTargets[account][target] = true;
97
+ targetLists[account].push(target);
98
+
99
+ emit AllowedTargetAdded(account, target);
100
+ }
101
+
102
+ function _clearAllowedTargets(address account) internal {
103
+ address[] storage targets = targetLists[account];
104
+ uint256 length = targets.length;
105
+ for (uint256 i = 0; i < length; i += 1) {
106
+ delete allowedTargets[account][targets[i]];
107
+ }
108
+ delete targetLists[account];
109
+ }
110
+ }
@@ -0,0 +1,263 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import '@matterlabs/zksync-contracts/contracts/system-contracts/libraries/TransactionHelper.sol';
5
+ import '@openzeppelin/contracts/utils/introspection/ERC165.sol';
6
+ import './IValidationHook.sol';
7
+
8
+ contract TargetSelectorAllowlistHook is ERC165, IValidationHook {
9
+ struct SelectorRule {
10
+ address target;
11
+ bytes4 selector;
12
+ }
13
+
14
+ mapping(address => bool) public enabled;
15
+ mapping(address => mapping(address => bool)) public allowedTargets;
16
+ mapping(address => mapping(address => mapping(bytes4 => bool))) public allowedSelectors;
17
+ mapping(address => address[]) private targetLists;
18
+ mapping(address => SelectorRule[]) private selectorRuleLists;
19
+
20
+ event AllowedTargetAdded(address indexed account, address indexed target);
21
+ event AllowedTargetRemoved(address indexed account, address indexed target);
22
+ event AllowedSelectorAdded(address indexed account, address indexed target, bytes4 indexed selector);
23
+ event AllowedSelectorRemoved(
24
+ address indexed account,
25
+ address indexed target,
26
+ bytes4 indexed selector
27
+ );
28
+
29
+ function init(bytes calldata initData) external override {
30
+ (address[] memory targets, SelectorRule[] memory selectorRules) = abi.decode(
31
+ initData,
32
+ (address[], SelectorRule[])
33
+ );
34
+
35
+ enabled[msg.sender] = true;
36
+
37
+ uint256 targetLength = targets.length;
38
+ for (uint256 i = 0; i < targetLength; i += 1) {
39
+ _addAllowedTarget(msg.sender, targets[i]);
40
+ }
41
+
42
+ uint256 selectorRuleLength = selectorRules.length;
43
+ for (uint256 i = 0; i < selectorRuleLength; i += 1) {
44
+ SelectorRule memory rule = selectorRules[i];
45
+ _addAllowedSelector(msg.sender, rule.target, rule.selector);
46
+ }
47
+
48
+ emit Inited(msg.sender);
49
+ }
50
+
51
+ function disable() external override {
52
+ require(enabled[msg.sender], 'Selector allowlist hook is not enabled');
53
+ _clearAllowedTargets(msg.sender);
54
+ _clearAllowedSelectors(msg.sender);
55
+ enabled[msg.sender] = false;
56
+ emit Disabled(msg.sender);
57
+ }
58
+
59
+ function isInited(address account) external view override returns (bool) {
60
+ return enabled[account];
61
+ }
62
+
63
+ function state(address account)
64
+ external
65
+ view
66
+ returns (
67
+ bool accountEnabled,
68
+ address[] memory targets,
69
+ SelectorRule[] memory selectorRules
70
+ )
71
+ {
72
+ return (enabled[account], targetLists[account], selectorRuleLists[account]);
73
+ }
74
+
75
+ function isTargetAllowed(address account, address target) external view returns (bool) {
76
+ return allowedTargets[account][target];
77
+ }
78
+
79
+ function isSelectorAllowed(address account, address target, bytes4 selector)
80
+ external
81
+ view
82
+ returns (bool)
83
+ {
84
+ return allowedSelectors[account][target][selector];
85
+ }
86
+
87
+ function addAllowedTarget(address target) external {
88
+ require(enabled[msg.sender], 'Selector allowlist hook is not enabled');
89
+ _addAllowedTarget(msg.sender, target);
90
+ }
91
+
92
+ function removeAllowedTarget(address target) external {
93
+ require(enabled[msg.sender], 'Selector allowlist hook is not enabled');
94
+ require(allowedTargets[msg.sender][target], 'Target is not allowlisted');
95
+
96
+ delete allowedTargets[msg.sender][target];
97
+
98
+ address[] storage targets = targetLists[msg.sender];
99
+ uint256 length = targets.length;
100
+ for (uint256 i = 0; i < length; i += 1) {
101
+ if (targets[i] == target) {
102
+ uint256 lastIndex = length - 1;
103
+ if (i != lastIndex) {
104
+ targets[i] = targets[lastIndex];
105
+ }
106
+ targets.pop();
107
+ break;
108
+ }
109
+ }
110
+
111
+ emit AllowedTargetRemoved(msg.sender, target);
112
+ }
113
+
114
+ function addAllowedSelector(address target, bytes4 selector) external {
115
+ require(enabled[msg.sender], 'Selector allowlist hook is not enabled');
116
+ _addAllowedSelector(msg.sender, target, selector);
117
+ }
118
+
119
+ function removeAllowedSelector(address target, bytes4 selector) external {
120
+ require(enabled[msg.sender], 'Selector allowlist hook is not enabled');
121
+ require(
122
+ allowedSelectors[msg.sender][target][selector],
123
+ 'Target selector is not allowlisted'
124
+ );
125
+
126
+ delete allowedSelectors[msg.sender][target][selector];
127
+
128
+ SelectorRule[] storage selectorRules = selectorRuleLists[msg.sender];
129
+ uint256 length = selectorRules.length;
130
+ for (uint256 i = 0; i < length; i += 1) {
131
+ SelectorRule storage rule = selectorRules[i];
132
+ if (rule.target == target && rule.selector == selector) {
133
+ uint256 lastIndex = length - 1;
134
+ if (i != lastIndex) {
135
+ selectorRules[i] = selectorRules[lastIndex];
136
+ }
137
+ selectorRules.pop();
138
+ break;
139
+ }
140
+ }
141
+
142
+ emit AllowedSelectorRemoved(msg.sender, target, selector);
143
+ }
144
+
145
+ function validationHook(bytes32, Transaction calldata transaction) external view override {
146
+ if (!enabled[msg.sender]) {
147
+ return;
148
+ }
149
+
150
+ address target = address(uint160(transaction.to));
151
+ if (target == msg.sender) {
152
+ return;
153
+ }
154
+
155
+ if (transaction.data.length < 4) {
156
+ require(allowedTargets[msg.sender][target], 'Target is not allowlisted');
157
+ return;
158
+ }
159
+
160
+ bytes4 selector = _selector(transaction.data);
161
+ require(
162
+ allowedSelectors[msg.sender][target][selector],
163
+ 'Target selector is not allowlisted'
164
+ );
165
+ }
166
+
167
+ function debugValidation(address account, Transaction calldata transaction)
168
+ external
169
+ view
170
+ returns (
171
+ bool accountEnabled,
172
+ address target,
173
+ uint256 dataLength,
174
+ bytes4 selector,
175
+ bool targetAllowed,
176
+ bool selectorAllowed,
177
+ bool wouldAllow
178
+ )
179
+ {
180
+ accountEnabled = enabled[account];
181
+ target = address(uint160(transaction.to));
182
+ dataLength = transaction.data.length;
183
+ targetAllowed = allowedTargets[account][target];
184
+ wouldAllow = !accountEnabled;
185
+
186
+ if (target == account) {
187
+ return (accountEnabled, target, dataLength, bytes4(0), targetAllowed, false, true);
188
+ }
189
+
190
+ if (dataLength < 4) {
191
+ return (
192
+ accountEnabled,
193
+ target,
194
+ dataLength,
195
+ bytes4(0),
196
+ targetAllowed,
197
+ false,
198
+ targetAllowed
199
+ );
200
+ }
201
+
202
+ selector = _selector(transaction.data);
203
+ selectorAllowed = allowedSelectors[account][target][selector];
204
+ wouldAllow = !accountEnabled || selectorAllowed;
205
+ }
206
+
207
+ function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
208
+ return interfaceId == type(IValidationHook).interfaceId || super.supportsInterface(interfaceId);
209
+ }
210
+
211
+ function _selector(bytes calldata data) internal pure returns (bytes4 selector) {
212
+ selector = bytes4(
213
+ (uint32(uint8(data[0])) << 24)
214
+ | (uint32(uint8(data[1])) << 16)
215
+ | (uint32(uint8(data[2])) << 8)
216
+ | uint32(uint8(data[3]))
217
+ );
218
+ }
219
+
220
+ function _addAllowedTarget(address account, address target) internal {
221
+ require(target != address(0), 'Target must not be zero');
222
+ require(target != account, 'Account self-target is implicit');
223
+ require(!allowedTargets[account][target], 'Target already allowlisted');
224
+
225
+ allowedTargets[account][target] = true;
226
+ targetLists[account].push(target);
227
+
228
+ emit AllowedTargetAdded(account, target);
229
+ }
230
+
231
+ function _addAllowedSelector(address account, address target, bytes4 selector) internal {
232
+ require(target != address(0), 'Target must not be zero');
233
+ require(target != account, 'Account self-target is implicit');
234
+ require(
235
+ !allowedSelectors[account][target][selector],
236
+ 'Target selector already allowlisted'
237
+ );
238
+
239
+ allowedSelectors[account][target][selector] = true;
240
+ selectorRuleLists[account].push(SelectorRule({ target: target, selector: selector }));
241
+
242
+ emit AllowedSelectorAdded(account, target, selector);
243
+ }
244
+
245
+ function _clearAllowedTargets(address account) internal {
246
+ address[] storage targets = targetLists[account];
247
+ uint256 length = targets.length;
248
+ for (uint256 i = 0; i < length; i += 1) {
249
+ delete allowedTargets[account][targets[i]];
250
+ }
251
+ delete targetLists[account];
252
+ }
253
+
254
+ function _clearAllowedSelectors(address account) internal {
255
+ SelectorRule[] storage selectorRules = selectorRuleLists[account];
256
+ uint256 length = selectorRules.length;
257
+ for (uint256 i = 0; i < length; i += 1) {
258
+ SelectorRule storage rule = selectorRules[i];
259
+ delete allowedSelectors[account][rule.target][rule.selector];
260
+ }
261
+ delete selectorRuleLists[account];
262
+ }
263
+ }
@@ -0,0 +1,76 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import '@matterlabs/zksync-contracts/contracts/system-contracts/libraries/TransactionHelper.sol';
5
+ import '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';
6
+ import './Auth.sol';
7
+ import './IValidationHook.sol';
8
+
9
+ abstract contract ValidationHookManager is Auth {
10
+ using ERC165Checker for address;
11
+
12
+ mapping(address => bool) public validationHooks;
13
+ address[] internal validationHookList;
14
+
15
+ event ValidationHookAdded(address indexed hook);
16
+ event ValidationHookRemoved(address indexed hook);
17
+
18
+ function addValidationHook(address hook, bytes calldata initData) external onlySelf {
19
+ _addValidationHook(hook, initData);
20
+ }
21
+
22
+ function removeValidationHook(address hook) external onlySelf {
23
+ _removeValidationHook(hook);
24
+ }
25
+
26
+ function listValidationHooks() external view returns (address[] memory hooks) {
27
+ hooks = validationHookList;
28
+ }
29
+
30
+ function _addValidationHook(address hook, bytes calldata initData) internal {
31
+ require(hook != address(0), 'Hook must not be zero');
32
+ require(hook != address(this), 'Account can not be a hook');
33
+ require(hook.code.length > 0, 'Hook must be a deployed contract');
34
+ require(!validationHooks[hook], 'Hook already enabled');
35
+ require(
36
+ hook.supportsInterface(type(IValidationHook).interfaceId),
37
+ 'Hook does not support validation interface'
38
+ );
39
+
40
+ validationHooks[hook] = true;
41
+ validationHookList.push(hook);
42
+ IValidationHook(hook).init(initData);
43
+ emit ValidationHookAdded(hook);
44
+ }
45
+
46
+ function _removeValidationHook(address hook) internal {
47
+ require(validationHooks[hook], 'Hook is not enabled');
48
+ delete validationHooks[hook];
49
+
50
+ uint256 length = validationHookList.length;
51
+ for (uint256 i = 0; i < length; i += 1) {
52
+ if (validationHookList[i] == hook) {
53
+ uint256 lastIndex = length - 1;
54
+ if (i != lastIndex) {
55
+ validationHookList[i] = validationHookList[lastIndex];
56
+ }
57
+ validationHookList.pop();
58
+ break;
59
+ }
60
+ }
61
+
62
+ try IValidationHook(hook).disable() {} catch {}
63
+
64
+ emit ValidationHookRemoved(hook);
65
+ }
66
+
67
+ function _runValidationHooks(
68
+ bytes32 signedHash,
69
+ Transaction calldata transaction
70
+ ) internal {
71
+ uint256 length = validationHookList.length;
72
+ for (uint256 i = 0; i < length; i += 1) {
73
+ IValidationHook(validationHookList[i]).validationHook(signedHash, transaction);
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,31 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.17;
3
+
4
+ import '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';
5
+ import './Auth.sol';
6
+ import './IValidator.sol';
7
+
8
+ abstract contract ValidatorManager is Auth {
9
+ using ERC165Checker for address;
10
+
11
+ address public validator;
12
+
13
+ event ValidatorChanged(address indexed previousValidator, address indexed newValidator);
14
+
15
+ function setValidator(address newValidator) external onlySelf {
16
+ _setValidator(newValidator);
17
+ }
18
+
19
+ function _setValidator(address newValidator) internal {
20
+ require(newValidator != address(0), 'Validator must not be zero');
21
+ require(newValidator != address(this), 'Account can not be a validator');
22
+ require(newValidator.code.length > 0, 'Validator must be a deployed contract');
23
+ require(
24
+ newValidator.supportsInterface(type(IK1Validator).interfaceId),
25
+ 'Validator does not support K1 interface'
26
+ );
27
+
28
+ emit ValidatorChanged(validator, newValidator);
29
+ validator = newValidator;
30
+ }
31
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@zk-agent/account-profiles",
3
+ "private": true,
4
+ "type": "module"
5
+ }
@@ -0,0 +1 @@
1
+ :root{color:#e7eefb;background:radial-gradient(circle at top,rgba(236,186,66,.18),transparent 38%),radial-gradient(circle at 20% 20%,rgba(61,135,255,.18),transparent 30%),linear-gradient(180deg,#091120,#050a14);font-family:IBM Plex Sans,Segoe UI,sans-serif}*{box-sizing:border-box}body{margin:0;min-height:100vh}.page{min-height:100vh;display:grid;place-items:center;padding:24px}.card{width:min(860px,100%);padding:32px;border-radius:24px;background:#080f1feb;border:1px solid rgba(122,145,201,.22);box-shadow:0 30px 80px #00000059}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.16em;color:#9fc0ff;font-size:12px}h1{margin:0 0 12px;font-size:36px}.lede{margin:0 0 24px;color:#b7c6e7;line-height:1.6}.meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin:0 0 24px}.meta div{padding:14px 16px;border-radius:16px;background:#131c35f2;border:1px solid rgba(145,162,204,.18)}.meta dt{color:#8fa3d7;font-size:12px;text-transform:uppercase;margin-bottom:6px}.meta dd{margin:0;font-family:Cascadia Code,Consolas,monospace;word-break:break-word}.callout{padding:16px 18px;border-radius:18px;background:#2c4c9133;color:#d7e1fb}.panel{margin-top:22px;padding:18px;border-radius:18px;background:#0d172de6;border:1px solid rgba(122,145,201,.14)}.panel-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}.panel h2{margin:0;font-size:18px}.state-pill{padding:8px 12px;border-radius:999px;font-family:Cascadia Code,Consolas,monospace;font-size:12px;text-transform:uppercase;letter-spacing:.08em}.state-pill--good{background:#47c48a29;border:1px solid rgba(71,196,138,.28);color:#9cf0c3}.state-pill--warn{background:#efbe5424;border:1px solid rgba(239,190,84,.22);color:#f7df9f}.state-pill--bad{background:#ff727224;border:1px solid rgba(255,114,114,.24);color:#ffb1b1}.state-pill--muted{background:#7a91c91f;border:1px solid rgba(122,145,201,.2);color:#c2d1f3}.chip-row{display:flex;flex-wrap:wrap;gap:10px}.chip{padding:8px 12px;border-radius:999px;background:#efbe541f;border:1px solid rgba(239,190,84,.18);color:#f7df9f;font-family:Cascadia Code,Consolas,monospace;font-size:12px}.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.form-grid label{display:grid;gap:8px}.form-grid span,.helper,.status{color:#9eb2de;font-size:14px}.helper-stack{display:grid;gap:8px;margin-bottom:14px}.helper-stack code,.status code{font-family:Cascadia Code,Consolas,monospace;color:#e7eefb}.field-stack{display:grid;gap:8px}.field-stack span{color:#9eb2de;font-size:14px}.form-grid input,.payload{width:100%;border:1px solid rgba(122,145,201,.24);border-radius:14px;background:#040a16f5;color:#e7eefb;padding:12px 14px;font:inherit}.payload{min-height:220px;margin-top:12px;resize:vertical;font-family:Cascadia Code,Consolas,monospace;font-size:13px;line-height:1.5}.command-block{width:100%;min-height:88px;border:1px solid rgba(122,145,201,.24);border-radius:14px;background:#040a16f5;color:#e7eefb;padding:12px 14px;resize:vertical;font:13px/1.5 Cascadia Code,Consolas,monospace}.actions{display:flex;align-items:center;flex-wrap:wrap;gap:14px;margin-top:14px}.compact-meta{margin-bottom:0}button{border:0;border-radius:999px;padding:12px 18px;background:linear-gradient(135deg,#f2cc63,#db9a2f);color:#1e1606;font-weight:700;cursor:pointer}button:disabled{cursor:not-allowed;opacity:.45}.button-secondary{background:#7a91c91f;color:#d7e1fb;border:1px solid rgba(122,145,201,.24);font-weight:600}.status-error{color:#ffb1b1}@media (max-width: 720px){.card{padding:22px;border-radius:20px}h1{font-size:30px}.panel-header{align-items:flex-start;flex-direction:column}}