@cofhe/mock-contracts 0.1.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/README.md +126 -0
- package/contracts/MockACL.sol +338 -0
- package/contracts/MockCoFHE.sol +441 -0
- package/contracts/MockQueryDecrypter.sol +133 -0
- package/contracts/MockTaskManager.sol +593 -0
- package/contracts/MockZkVerifier.sol +140 -0
- package/contracts/Permissioned.sol +213 -0
- package/contracts/TestBed.sol +66 -0
- package/contracts/foundry/CoFheTest.sol +432 -0
- package/contracts/foundry/MockZkVerifierSigner.sol +40 -0
- package/dist/index.d.mts +261 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.js +2488 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2482 -0
- package/dist/index.mjs.map +1 -0
- package/foundry.toml +7 -0
- package/package.json +55 -0
- package/remappings.txt +5 -0
- package/test/TestBed.t.sol +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# @fhenixprotocol/cofhe-mock-contracts [![NPM Package][npm-badge]][npm] [![License: MIT][license-badge]][license]
|
|
2
|
+
|
|
3
|
+
[npm]: https://www.npmjs.com/package/@fhenixprotocol/cofhe-mock-contracts
|
|
4
|
+
[npm-badge]: https://img.shields.io/npm/v/@fhenixprotocol/cofhe-mock-contracts.svg
|
|
5
|
+
[license]: https://opensource.org/licenses/MIT
|
|
6
|
+
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
|
|
7
|
+
|
|
8
|
+
A mock smart contract library for testing CoFHE (Confidential Computing Framework for Homomorphic Encryption) with FHE primitives. This package provides mock implementations of core CoFHE contracts for development and testing purposes.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Mock implementations of core CoFHE contracts:
|
|
13
|
+
- MockTaskManager
|
|
14
|
+
- MockQueryDecrypter
|
|
15
|
+
- MockZkVerifier
|
|
16
|
+
- ACL (Access Control List)
|
|
17
|
+
- Synchronous operation simulation with mock delays
|
|
18
|
+
- On-chain access to unencrypted values for testing
|
|
19
|
+
- Compatible with the main `@fhenixprotocol/cofhe-contracts` package
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
npm
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @fhenixprotocol/cofhe-mock-contracts
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
foundry
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
forge install fhenixprotocol/cofhe-mock-contracts
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usages and Integrations
|
|
36
|
+
|
|
37
|
+
`@cofhe/sdk` is designed to work with mock contracts in a testing / hardhat environment. `cofhesdk/hardhat-plugin` deploys the mock contracts in this repo, and the `cofhesdkClient` detects a testnet chain and interacts correctly using the mocks rather than the true CoFHE coprocessor.
|
|
38
|
+
|
|
39
|
+
When installed and imported in the `hardhat.config.ts`, `cofhesdk/hardhat-plugin` will watch for Hardhat `node` and `test` tasks, and will deploy the mocks to the hardhat testnet chain at fixed addresses.
|
|
40
|
+
|
|
41
|
+
Once deployed, interaction with the mock contracts is handled by the `cofhesdkClient` (created with `createCofhesdkClient(...)`). The client checks for the existence of mock contracts at known addresses, and if they exist, marks the current connection as a testnet.
|
|
42
|
+
|
|
43
|
+
## Logging
|
|
44
|
+
|
|
45
|
+
By default the mock CoFHE contracts log the internal "FHE" operations using `hardhat/console.sol`. Logs can be enabled or disabled using the `setLogOps()` function in `MockTaskManager.sol`.
|
|
46
|
+
|
|
47
|
+
## Differences between Cofhe and Mocks
|
|
48
|
+
|
|
49
|
+
### Symbolic Execution
|
|
50
|
+
|
|
51
|
+
The CoFHE coprocessor uses symbolic execution when performing operations on chain. Each ciphertext exists off-chain, and is represented by an on-chain ciphertext hash (`ctHash`).
|
|
52
|
+
|
|
53
|
+
FHE operations between one or more `ctHash`es returns a resultant `ctHash`, which is symbolically linked to the true `ciphertext` which includes the encrypted values.
|
|
54
|
+
|
|
55
|
+
In `cofhe-mock-contracts` the symbolic execution is preserved. In the case of the mocks, the `ciphertext` is not encrypted to be used in the FHE scheme, but is stored as a plaintext value. In this case, the `ctHash` associated with the `ciphertext` is pointing directly at the plaintext value instead.
|
|
56
|
+
|
|
57
|
+
During the execution of a mock FHE operation, say `FHE.add(euint8 ctHashA, euint8 ctHashB) -> euint8 ctHashC`, rather than being performed off-chain by the FHE computation engine, the input `ctHashes` are mapped to their plaintext value, and the operation performed as plaintext math on-chain. The result is inserted into the symbolic value position of `ctHashC`.
|
|
58
|
+
|
|
59
|
+
### On-chain Decryption
|
|
60
|
+
|
|
61
|
+
CoFHE coprocessor handles on-chain decryption requests asynchronously. Once the decryption is requested with `FHE.decrypt(...)` the decryption will be performed off-chain by CoFHE, and the result posted on-chain in the `PlaintextStorage` module of `TaskManager`. The decryption result can then checked using either `FHE.getDecryptResult(...)` or `FHE.getDecryptResultSafe(...)`.
|
|
62
|
+
|
|
63
|
+
When a mock decryption is requested, a random number between 1 and 10 is generated to determine how many seconds the mock decryption async duration. Though the decryption result is available immediately within the mock contracts, the async duration is added to mimic the off-chain decryption and posting time.
|
|
64
|
+
|
|
65
|
+
### ZkVerifying
|
|
66
|
+
|
|
67
|
+
A key component of CoFHE is the ability to pre-encrypt inputs in a secure and verifiable way. `cofhesdk` prepares these inputs automatically, and requests a verification signature from the coprocessor `ZkVerifier` module. The zkVerifier returns a signature indicating that the encrypted ciphertext is valid, and has been stored on the Fhenix L2 blockchain.
|
|
68
|
+
|
|
69
|
+
The mocks are then responsible for mocking two actions:
|
|
70
|
+
|
|
71
|
+
1. Creating the signature.
|
|
72
|
+
2. Storing the plaintext value on-chain.
|
|
73
|
+
|
|
74
|
+
The `MockZkVerifier` contract handles the on-chain storage of encrypted inputs. The signature creation is handled automatically within `cofhesdkClient.encryptInputs` when executing against a testnet.
|
|
75
|
+
|
|
76
|
+
### Off-chain Decryption / Sealing
|
|
77
|
+
|
|
78
|
+
Off-chain decryption is performed by calling the `cofhesdkClient.decryptHandle` function with a valid `ctHash` and a valid `permit` [todo link].
|
|
79
|
+
|
|
80
|
+
When interacting with CoFHE this request is routed to the Threshold Network, which will perform the decryption operation, ultimately returning a decrypted result.
|
|
81
|
+
|
|
82
|
+
When working with the mocks, the `cofhesdkClient` will instead query the `MockQueryDecrypter` contract, which will verify the request `permit`, and return the decrypted result.
|
|
83
|
+
|
|
84
|
+
### Using Foundry
|
|
85
|
+
|
|
86
|
+
> **Important**: You must set `isolate = true` in your `foundry.toml`. Without this setting, some variables may be used without proper permission checks, which will cause failures on production chains.
|
|
87
|
+
|
|
88
|
+
Use abstract CoFheTest contract to automatically deploy all necessary FHE contracts for testing.
|
|
89
|
+
|
|
90
|
+
CoFheTest also exposes useful test methods such as
|
|
91
|
+
|
|
92
|
+
- `assertHashValue(euint, uint)` - asserting an encrypted value is equal to an expected plaintext value
|
|
93
|
+
- `createInEuint..(number, user)` - for creating encrypted inputs (8-256bits) for a given user
|
|
94
|
+
|
|
95
|
+
see `contracts/TestBed.sol` for the original contract
|
|
96
|
+
|
|
97
|
+
```solidity
|
|
98
|
+
import {Test} from "forge-std/Test.sol";
|
|
99
|
+
import {CoFheTest} from "@fhenixprotocol/cofhe-contracts/FHE.sol";
|
|
100
|
+
...
|
|
101
|
+
contract TestBed is Test, CoFheTest {
|
|
102
|
+
|
|
103
|
+
TestBed private testbed;
|
|
104
|
+
|
|
105
|
+
address private user = makeAddr("user");
|
|
106
|
+
|
|
107
|
+
function setUp() public {
|
|
108
|
+
// optional ... enable verbose logging for fhe mocks
|
|
109
|
+
// setLog(true);
|
|
110
|
+
|
|
111
|
+
testbed = new TestBed();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function testSetNumber() public {
|
|
115
|
+
uint32 n = 10;
|
|
116
|
+
InEuint32 memory number = createInEuint32(n, user);
|
|
117
|
+
|
|
118
|
+
//must be the user who sends transaction
|
|
119
|
+
//or else invalid permissions from fhe allow
|
|
120
|
+
vm.prank(user);
|
|
121
|
+
testbed.setNumber(number);
|
|
122
|
+
|
|
123
|
+
assertHashValue(testbed.eNumber(), n);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
2
|
+
// solhint-disable-next-line transient-storage
|
|
3
|
+
pragma solidity >=0.8.25 <0.9.0;
|
|
4
|
+
|
|
5
|
+
import { Strings } from '@openzeppelin/contracts/utils/Strings.sol';
|
|
6
|
+
import { MockPermissioned, Permission } from './Permissioned.sol';
|
|
7
|
+
import { TASK_MANAGER_ADDRESS } from '@fhenixprotocol/cofhe-contracts/FHE.sol';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title ACL
|
|
11
|
+
* @notice The ACL (Access Control List) is a permission management system designed to
|
|
12
|
+
* control who can access, compute on, or decrypt encrypted values in cofhe.
|
|
13
|
+
* By defining and enforcing these permissions, the ACL ensures that encrypted data remains secure while still being usable
|
|
14
|
+
* within authorized contexts.
|
|
15
|
+
*/
|
|
16
|
+
contract MockACL is MockPermissioned {
|
|
17
|
+
/// @notice Returned if the delegatee contract is already delegatee for sender & delegator addresses.
|
|
18
|
+
error AlreadyDelegated();
|
|
19
|
+
|
|
20
|
+
/// @notice Returned if the sender is the delegatee address.
|
|
21
|
+
error SenderCannotBeDelegateeAddress();
|
|
22
|
+
|
|
23
|
+
/// @notice Returned if the sender address is not allowed for allow operations.
|
|
24
|
+
/// @param sender Sender address.
|
|
25
|
+
error SenderNotAllowed(address sender);
|
|
26
|
+
|
|
27
|
+
/// @notice Returned if the user is trying to directly allow a handle (not via Task Manager).
|
|
28
|
+
/// @param sender Sender address.
|
|
29
|
+
error DirectAllowForbidden(address sender);
|
|
30
|
+
|
|
31
|
+
/// @notice Emitted when a list of handles is allowed for decryption.
|
|
32
|
+
/// @param handlesList List of handles allowed for decryption.
|
|
33
|
+
event AllowedForDecryption(uint256[] handlesList);
|
|
34
|
+
|
|
35
|
+
/// @notice Emitted when a new delegate address is added.
|
|
36
|
+
/// @param sender Sender address
|
|
37
|
+
/// @param delegatee Delegatee address.
|
|
38
|
+
/// @param contractAddress Contract address.
|
|
39
|
+
event NewDelegation(address indexed sender, address indexed delegatee, address indexed contractAddress);
|
|
40
|
+
|
|
41
|
+
/// @custom:storage-location erc7201:cofhe.storage.ACL
|
|
42
|
+
struct ACLStorage {
|
|
43
|
+
mapping(uint256 handle => bool isGlobal) globalHandles;
|
|
44
|
+
mapping(uint256 handle => mapping(address account => bool isAllowed)) persistedAllowedPairs;
|
|
45
|
+
mapping(uint256 => bool) allowedForDecryption;
|
|
46
|
+
mapping(address account => mapping(address delegatee => mapping(address contractAddress => bool isDelegate))) delegates;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/// @notice Name of the contract.
|
|
50
|
+
string private constant CONTRACT_NAME = 'ACL';
|
|
51
|
+
|
|
52
|
+
/// @notice Major version of the contract.
|
|
53
|
+
uint256 private constant MAJOR_VERSION = 0;
|
|
54
|
+
|
|
55
|
+
/// @notice Minor version of the contract.
|
|
56
|
+
uint256 private constant MINOR_VERSION = 1;
|
|
57
|
+
|
|
58
|
+
/// @notice Patch version of the contract.
|
|
59
|
+
uint256 private constant PATCH_VERSION = 0;
|
|
60
|
+
|
|
61
|
+
/// @notice TaskManagerAddress address.
|
|
62
|
+
address public constant TASK_MANAGER_ADDRESS_ = TASK_MANAGER_ADDRESS;
|
|
63
|
+
|
|
64
|
+
/// @dev keccak256(abi.encode(uint256(keccak256("cofhe.storage.ACL")) - 1)) & ~bytes32(uint256(0xff))
|
|
65
|
+
bytes32 private constant ACL_SLOT =
|
|
66
|
+
keccak256(abi.encode(uint256(keccak256('cofhe.storage.ACL')) - 1)) & ~bytes32(uint256(0xff));
|
|
67
|
+
|
|
68
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
69
|
+
constructor() {}
|
|
70
|
+
|
|
71
|
+
function exists() public pure returns (bool) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @notice Allows the use of `handle` for the address `account`.
|
|
77
|
+
* @dev The caller must be allowed to use `handle` for allow() to succeed. If not, allow() reverts.
|
|
78
|
+
* @param handle Handle.
|
|
79
|
+
* @param account Address of the account being given permissions.
|
|
80
|
+
* @param requester Address of the account giving the permissions.
|
|
81
|
+
*/
|
|
82
|
+
function allow(uint256 handle, address account, address requester) public virtual {
|
|
83
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
84
|
+
revert DirectAllowForbidden(msg.sender);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!isAllowed(handle, requester)) {
|
|
88
|
+
revert SenderNotAllowed(requester);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
ACLStorage storage $ = _getACLStorage();
|
|
92
|
+
$.persistedAllowedPairs[handle][account] = true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @notice Allows the use of `handle` globally (all accounts).
|
|
97
|
+
* @dev The caller must be allowed to use `handle` for allowGlobal() to succeed. If not, allowGlobal() reverts.
|
|
98
|
+
* @param handle Handle.
|
|
99
|
+
* @param requester Address of the account giving the permissions.
|
|
100
|
+
*/
|
|
101
|
+
function allowGlobal(uint256 handle, address requester) public virtual {
|
|
102
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
103
|
+
revert DirectAllowForbidden(msg.sender);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!isAllowed(handle, requester)) {
|
|
107
|
+
revert SenderNotAllowed(requester);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
ACLStorage storage $ = _getACLStorage();
|
|
111
|
+
|
|
112
|
+
$.globalHandles[handle] = true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @notice Allows a list of handles to be decrypted.
|
|
117
|
+
* @param handlesList List of handles.
|
|
118
|
+
*/
|
|
119
|
+
function allowForDecryption(uint256[] memory handlesList, address requester) public virtual {
|
|
120
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
121
|
+
revert DirectAllowForbidden(msg.sender);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
uint256 len = handlesList.length;
|
|
125
|
+
ACLStorage storage $ = _getACLStorage();
|
|
126
|
+
|
|
127
|
+
for (uint256 k = 0; k < len; k++) {
|
|
128
|
+
uint256 handle = handlesList[k];
|
|
129
|
+
if (!isAllowed(handle, requester)) {
|
|
130
|
+
revert SenderNotAllowed(requester);
|
|
131
|
+
}
|
|
132
|
+
$.allowedForDecryption[handle] = true;
|
|
133
|
+
}
|
|
134
|
+
emit AllowedForDecryption(handlesList);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @notice Allows the use of `handle` by address `account` for this transaction.
|
|
139
|
+
* @dev The caller must be the Task Manager contract.
|
|
140
|
+
* @dev The requester must be allowed to use `handle` for allowTransient() to succeed.
|
|
141
|
+
* If not, allowTransient() reverts.
|
|
142
|
+
* @param handle Handle.
|
|
143
|
+
* @param account Address of the account.
|
|
144
|
+
* @param requester Address of the requester.
|
|
145
|
+
*/
|
|
146
|
+
function allowTransient(uint256 handle, address account, address requester) public virtual {
|
|
147
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
148
|
+
revert DirectAllowForbidden(msg.sender);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!isAllowed(handle, requester) && requester != TASK_MANAGER_ADDRESS_) {
|
|
152
|
+
revert SenderNotAllowed(requester);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bytes32 key = keccak256(abi.encodePacked(handle, account));
|
|
156
|
+
assembly {
|
|
157
|
+
// solc-ignore-next-line transient-storage
|
|
158
|
+
tstore(key, 1)
|
|
159
|
+
let length := tload(0)
|
|
160
|
+
let lengthPlusOne := add(length, 1)
|
|
161
|
+
// solc-ignore-next-line transient-storage
|
|
162
|
+
tstore(lengthPlusOne, key)
|
|
163
|
+
// solc-ignore-next-line transient-storage
|
|
164
|
+
tstore(0, lengthPlusOne)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @notice Delegates the access of `handles` in the context of account abstraction for issuing
|
|
170
|
+
* reencryption requests from a smart contract account.
|
|
171
|
+
* @param delegatee Delegatee address.
|
|
172
|
+
* @param delegateeContract Delegatee contract.
|
|
173
|
+
*/
|
|
174
|
+
function delegateAccount(address delegatee, address delegateeContract) public virtual {
|
|
175
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
176
|
+
revert DirectAllowForbidden(msg.sender);
|
|
177
|
+
}
|
|
178
|
+
if (delegateeContract == msg.sender) {
|
|
179
|
+
revert SenderCannotBeDelegateeAddress();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
ACLStorage storage $ = _getACLStorage();
|
|
183
|
+
if ($.delegates[msg.sender][delegatee][delegateeContract]) {
|
|
184
|
+
revert AlreadyDelegated();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
$.delegates[msg.sender][delegatee][delegateeContract] = true;
|
|
188
|
+
emit NewDelegation(msg.sender, delegatee, delegateeContract);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @notice Returns whether the delegatee is allowed to access the handle.
|
|
193
|
+
* @param delegatee Delegatee address.
|
|
194
|
+
* @param handle Handle.
|
|
195
|
+
* @param contractAddress Contract address.
|
|
196
|
+
* @param account Address of the account.
|
|
197
|
+
* @return isAllowed Whether the handle can be accessed.
|
|
198
|
+
*/
|
|
199
|
+
function allowedOnBehalf(
|
|
200
|
+
address delegatee,
|
|
201
|
+
uint256 handle,
|
|
202
|
+
address contractAddress,
|
|
203
|
+
address account
|
|
204
|
+
) public view virtual returns (bool) {
|
|
205
|
+
ACLStorage storage $ = _getACLStorage();
|
|
206
|
+
return
|
|
207
|
+
$.persistedAllowedPairs[handle][account] &&
|
|
208
|
+
$.persistedAllowedPairs[handle][contractAddress] &&
|
|
209
|
+
$.delegates[account][delegatee][contractAddress];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @notice Checks whether the account is allowed to use the handle in the
|
|
214
|
+
* same transaction (transient).
|
|
215
|
+
* @param handle Handle.
|
|
216
|
+
* @param account Address of the account.
|
|
217
|
+
* @return isAllowedTransient Whether the account can access transiently the handle.
|
|
218
|
+
*/
|
|
219
|
+
function allowedTransient(uint256 handle, address account) public view virtual returns (bool) {
|
|
220
|
+
bool isAllowedTransient;
|
|
221
|
+
bytes32 key = keccak256(abi.encodePacked(handle, account));
|
|
222
|
+
assembly {
|
|
223
|
+
isAllowedTransient := tload(key)
|
|
224
|
+
}
|
|
225
|
+
return isAllowedTransient;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @notice Getter function for the TaskManager contract address.
|
|
230
|
+
* @return taskManagerAddress Address of the TaskManager.
|
|
231
|
+
*/
|
|
232
|
+
function getTaskManagerAddress() public view virtual returns (address) {
|
|
233
|
+
return TASK_MANAGER_ADDRESS_;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @notice Returns whether the account is allowed to use the `handle`, either due to
|
|
238
|
+
* allowTransient() or allow().
|
|
239
|
+
* @param handle Handle.
|
|
240
|
+
* @param account Address of the account.
|
|
241
|
+
* @return isAllowed Whether the account can access the handle.
|
|
242
|
+
*/
|
|
243
|
+
function isAllowed(uint256 handle, address account) public view virtual returns (bool) {
|
|
244
|
+
return allowedTransient(handle, account) || persistAllowed(handle, account) || globalAllowed(handle);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @notice Checks whether a handle is allowed for decryption.
|
|
249
|
+
* @param handle Handle.
|
|
250
|
+
* @return isAllowed Whether the handle is allowed for decryption.
|
|
251
|
+
*/
|
|
252
|
+
function isAllowedForDecryption(uint256 handle) public view virtual returns (bool) {
|
|
253
|
+
ACLStorage storage $ = _getACLStorage();
|
|
254
|
+
return $.allowedForDecryption[handle];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @notice Returns `true` if address `a` is allowed to use `c` and `false` otherwise.
|
|
259
|
+
* @param handle Handle.
|
|
260
|
+
* @param account Address of the account.
|
|
261
|
+
* @return isAllowed Whether the account can access the handle.
|
|
262
|
+
*/
|
|
263
|
+
function persistAllowed(uint256 handle, address account) public view virtual returns (bool) {
|
|
264
|
+
ACLStorage storage $ = _getACLStorage();
|
|
265
|
+
return $.persistedAllowedPairs[handle][account];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @notice Returns `true` if the handle is allowed globally.
|
|
270
|
+
* @param handle Handle.
|
|
271
|
+
* @return isAllowed Whether the handle is allowed globally.
|
|
272
|
+
*/
|
|
273
|
+
function globalAllowed(uint256 handle) public view virtual returns (bool) {
|
|
274
|
+
ACLStorage storage $ = _getACLStorage();
|
|
275
|
+
return $.globalHandles[handle];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @dev This function removes the transient allowances, which could be useful for integration with
|
|
280
|
+
* Account Abstraction when bundling several UserOps calling the TaskManagerCoprocessor.
|
|
281
|
+
*/
|
|
282
|
+
function cleanTransientStorage() external virtual {
|
|
283
|
+
if (msg.sender != TASK_MANAGER_ADDRESS_) {
|
|
284
|
+
revert DirectAllowForbidden(msg.sender);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
assembly {
|
|
288
|
+
let length := tload(0)
|
|
289
|
+
tstore(0, 0)
|
|
290
|
+
let lengthPlusOne := add(length, 1)
|
|
291
|
+
for {
|
|
292
|
+
let i := 1
|
|
293
|
+
} lt(i, lengthPlusOne) {
|
|
294
|
+
i := add(i, 1)
|
|
295
|
+
} {
|
|
296
|
+
let handle := tload(i)
|
|
297
|
+
tstore(i, 0)
|
|
298
|
+
tstore(handle, 0)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @notice Getter for the name and version of the contract.
|
|
305
|
+
* @return string Name and the version of the contract.
|
|
306
|
+
*/
|
|
307
|
+
function getVersion() external pure virtual returns (string memory) {
|
|
308
|
+
return
|
|
309
|
+
string(
|
|
310
|
+
abi.encodePacked(
|
|
311
|
+
CONTRACT_NAME,
|
|
312
|
+
' v',
|
|
313
|
+
Strings.toString(MAJOR_VERSION),
|
|
314
|
+
'.',
|
|
315
|
+
Strings.toString(MINOR_VERSION),
|
|
316
|
+
'.',
|
|
317
|
+
Strings.toString(PATCH_VERSION)
|
|
318
|
+
)
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @dev Returns the ACL storage location.
|
|
324
|
+
*/
|
|
325
|
+
function _getACLStorage() internal pure returns (ACLStorage storage $) {
|
|
326
|
+
bytes32 slot = ACL_SLOT;
|
|
327
|
+
assembly {
|
|
328
|
+
$.slot := slot
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function isAllowedWithPermission(
|
|
333
|
+
Permission memory permission,
|
|
334
|
+
uint256 handle
|
|
335
|
+
) public view withPermission(permission) returns (bool) {
|
|
336
|
+
return isAllowed(handle, permission.issuer);
|
|
337
|
+
}
|
|
338
|
+
}
|