@crisp-e3/contracts 0.5.8 → 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,12 +16,22 @@ import { HonkVerifier } from "./CRISPVerifier.sol";
16
16
  contract CRISPProgram is IE3Program, Ownable {
17
17
  using InternalLazyIMT for LazyIMTData;
18
18
 
19
+ /// @notice Enum to represent credit modes
20
+ enum CreditMode {
21
+ /// @notice Everyone has constant credits
22
+ CONSTANT,
23
+ /// @notice Credits are custom (can be based on token balance, etc)
24
+ CUSTOM
25
+ }
26
+
19
27
  /// @notice Struct to store all data related to a voting round
20
28
  struct RoundData {
21
29
  uint256 merkleRoot;
22
30
  bytes32 paramsHash;
23
31
  mapping(address slot => uint40 index) voteSlots;
24
32
  LazyIMTData votes;
33
+ uint256 numOptions;
34
+ CreditMode creditMode;
25
35
  }
26
36
 
27
37
  // Constants
@@ -29,6 +39,8 @@ contract CRISPProgram is IE3Program, Ownable {
29
39
  bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV");
30
40
  /// @notice The depth of the input Merkle tree.
31
41
  uint8 public constant TREE_DEPTH = 20;
42
+ /// @notice Maximum number of bits allocated for vote counts in the plaintext output per option.
43
+ uint256 constant MAX_VOTE_BITS = 50;
32
44
 
33
45
  // State variables
34
46
  IEnclave public enclave;
@@ -54,6 +66,7 @@ contract CRISPProgram is IE3Program, Ownable {
54
66
  error InvalidTallyLength();
55
67
  error SlotIsEmpty();
56
68
  error MerkleRootNotSet();
69
+ error InvalidNumOptions();
57
70
 
58
71
  // Events
59
72
  event InputPublished(uint256 indexed e3Id, bytes encryptedVote, uint256 index);
@@ -106,10 +119,25 @@ contract CRISPProgram is IE3Program, Ownable {
106
119
  }
107
120
 
108
121
  /// @inheritdoc IE3Program
109
- function validate(uint256 e3Id, uint256, bytes calldata e3ProgramParams, bytes calldata) external returns (bytes32) {
122
+ function validate(
123
+ uint256 e3Id,
124
+ uint256,
125
+ bytes calldata e3ProgramParams,
126
+ bytes calldata,
127
+ bytes calldata customParams
128
+ ) external returns (bytes32) {
110
129
  if (!authorizedContracts[msg.sender] && msg.sender != owner()) revert CallerNotAuthorized();
111
130
  if (e3Data[e3Id].paramsHash != bytes32(0)) revert E3AlreadyInitialized();
112
131
 
132
+ // decode custom params to get the number of options
133
+ (, , uint256 numOptions, CreditMode creditMode, ) = abi.decode(customParams, (address, uint256, uint256, CreditMode, uint256));
134
+ if (numOptions < 2) revert InvalidNumOptions();
135
+
136
+ // we need to know the number of options for decoding the tally
137
+ e3Data[e3Id].numOptions = numOptions;
138
+ // we want to save the credit more so it can be verified on chain by everyone
139
+ e3Data[e3Id].creditMode = creditMode;
140
+
113
141
  e3Data[e3Id].paramsHash = keccak256(e3ProgramParams);
114
142
 
115
143
  // Initialize the votes Merkle tree for this E3 ID.
@@ -139,13 +167,14 @@ contract CRISPProgram is IE3Program, Ownable {
139
167
  E3 memory e3 = enclave.getE3(e3Id);
140
168
 
141
169
  // Set the public inputs for the proof. Order must match Noir circuit.
142
- bytes32[] memory noirPublicInputs = new bytes32[](6);
170
+ bytes32[] memory noirPublicInputs = new bytes32[](7);
143
171
  noirPublicInputs[0] = previousEncryptedVoteCommitment;
144
172
  noirPublicInputs[1] = e3.committeePublicKey;
145
173
  noirPublicInputs[2] = bytes32(e3Data[e3Id].merkleRoot);
146
174
  noirPublicInputs[3] = bytes32(uint256(uint160(slotAddress)));
147
175
  noirPublicInputs[4] = bytes32(uint256(previousEncryptedVoteCommitment == bytes32(0) ? 1 : 0));
148
- noirPublicInputs[5] = encryptedVoteCommitment;
176
+ noirPublicInputs[5] = bytes32(e3Data[e3Id].numOptions);
177
+ noirPublicInputs[6] = encryptedVoteCommitment;
149
178
 
150
179
  // Check if the ciphertext was encrypted correctly
151
180
  if (!honkVerifier.verify(noirProof, noirPublicInputs)) {
@@ -157,30 +186,40 @@ contract CRISPProgram is IE3Program, Ownable {
157
186
 
158
187
  /// @notice Decode the tally from the plaintext output
159
188
  /// @param e3Id The E3 program ID
160
- /// @return yes The number of yes votes
161
- /// @return no The number of no votes
162
- function decodeTally(uint256 e3Id) public view returns (uint256 yes, uint256 no) {
163
- // fetch from enclave
189
+ /// @return votes - an array of vote counts for each option
190
+ function decodeTally(uint256 e3Id) public view returns (uint256[] memory votes) {
164
191
  E3 memory e3 = enclave.getE3(e3Id);
165
192
 
166
- // decode it into an array of uint64
193
+ uint256 numOptions = e3Data[e3Id].numOptions;
194
+
195
+ // If num optionsis not configured, return empty array to avoid decoding errors.
196
+ // Users might be calling this function too early and there's no
197
+ if (numOptions == 0) {
198
+ return new uint256[](0);
199
+ }
200
+
167
201
  uint64[] memory tally = _decodeBytesToUint64Array(e3.plaintextOutput);
168
202
 
169
- uint256 halfD = tally.length / 2;
203
+ uint256 segmentSize = tally.length / numOptions;
204
+ uint256 effectiveSize = segmentSize > MAX_VOTE_BITS ? MAX_VOTE_BITS : segmentSize;
170
205
 
171
- // Convert yes votes
172
- for (uint256 i = 0; i < halfD; i++) {
173
- uint256 weight = 2 ** (halfD - 1 - i);
174
- yes += tally[i] * weight;
175
- }
206
+ votes = new uint256[](numOptions);
207
+
208
+ for (uint256 optIdx = 0; optIdx < numOptions; optIdx++) {
209
+ uint256 segmentStart = optIdx * segmentSize;
210
+ // Read only the last effectiveSize bits (where the value is, MSB first)
211
+ uint256 readStart = segmentStart + segmentSize - effectiveSize;
212
+ uint256 value = 0;
213
+
214
+ for (uint256 i = 0; i < effectiveSize; i++) {
215
+ uint256 weight = 2 ** (effectiveSize - 1 - i);
216
+ value += uint256(tally[readStart + i]) * weight;
217
+ }
176
218
 
177
- // Convert no votes
178
- for (uint256 i = halfD; i < tally.length; i++) {
179
- uint256 weight = 2 ** (tally.length - 1 - i);
180
- no += tally[i] * weight;
219
+ votes[optIdx] = value;
181
220
  }
182
221
 
183
- return (yes, no);
222
+ return votes;
184
223
  }
185
224
 
186
225
  /// @notice Get the slot index for a given E3 ID and slot address
@@ -1,91 +1,88 @@
1
- // SPDX-License-Identifier: LGPL-3.0-only
2
- //
3
- // This file is provided WITHOUT ANY WARRANTY;
4
- // without even the implied warranty of MERCHANTABILITY
5
- // or FITNESS FOR A PARTICULAR PURPOSE.
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2022 Aztec
6
3
  pragma solidity >=0.8.21;
7
4
 
8
- uint256 constant N = 262144;
9
- uint256 constant LOG_N = 18;
10
- uint256 constant NUMBER_OF_PUBLIC_INPUTS = 22;
11
- uint256 constant VK_HASH = 0x0d53ba57f65358b21e53cf07b91c27906ac4d24b9205fda35494e1a44ba7242a;
5
+ uint256 constant N = 524288;
6
+ uint256 constant LOG_N = 19;
7
+ uint256 constant NUMBER_OF_PUBLIC_INPUTS = 23;
8
+ uint256 constant VK_HASH = 0x2349c3d182cb0307ecfa17d2cb91dcf9e7742a8daa67aa106831c761dd22030d;
12
9
  library HonkVerificationKey {
13
10
  function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) {
14
11
  Honk.VerificationKey memory vk = Honk.VerificationKey({
15
- circuitSize: uint256(262144),
16
- logCircuitSize: uint256(18),
17
- publicInputsSize: uint256(22),
12
+ circuitSize: uint256(524288),
13
+ logCircuitSize: uint256(19),
14
+ publicInputsSize: uint256(23),
18
15
  ql: Honk.G1Point({
19
- x: uint256(0x112a6aa13787457ce92f268d8f6719287c1add28a224712ea3e2e7d96e2bc70b),
20
- y: uint256(0x14dcf6e306f1dc722638d4984332053df53689114040ccd69d5926f485219e15)
16
+ x: uint256(0x253c5186ca1b682f7d302cd73b85ea3447a5a2c64fc82b70652f7fc44b203128),
17
+ y: uint256(0x14f602413e183c57d3d3124290ab48b6c8b0cbace773766a573ead30bf5c2f4f)
21
18
  }),
22
19
  qr: Honk.G1Point({
23
- x: uint256(0x22a648530332803c4a992d98fd94a036c8ff1341c3d0ba385210b8851049206c),
24
- y: uint256(0x0b891280448cdaee82da9caec22fb4820e3140558570c252669508b4f90fba2b)
20
+ x: uint256(0x2d20633d112c7c7efd2821f2860e9d1287f8f68ddd4b0216bb179078497a571c),
21
+ y: uint256(0x11928235f13ba529b1ee2f75fe26dda5ed5c79ec36028c09ad2bd8b957546344)
25
22
  }),
26
23
  qo: Honk.G1Point({
27
- x: uint256(0x1ca6c37b9177a348c574f214e0683da82632df5c0d10addde3f372cda3f8978a),
28
- y: uint256(0x22ce8ff67ba39a26d4ad603fbe668d9eb3f34f80b4e21e5cbf421d873f6ca040)
24
+ x: uint256(0x2b570f8e2eccc265f39b9e73778cf6e282554452adb19d2a2406952447d4aa6e),
25
+ y: uint256(0x14afd678c64e0dacd64724504e36bca6eccb5a477a5e2987b6543246b8135a90)
29
26
  }),
30
27
  q4: Honk.G1Point({
31
- x: uint256(0x0af0446ba584e461430e07a1f990aaee46d7b5088ad9f54d4a1350d57fa37ab6),
32
- y: uint256(0x152ab3b635c7f88c62d6bb37fdff5bed5e42e01e0f9894058c10deea1994e4ef)
28
+ x: uint256(0x2d7f53a245e9c855325eeb73c8fea788f5b457293cacfd7e3e332210a27a7d2f),
29
+ y: uint256(0x182d5ef8840426caa829856d7e800ee98509383d9ee637d1facbc11f7a8fba0d)
33
30
  }),
34
31
  qm: Honk.G1Point({
35
- x: uint256(0x2493bb0b6575f4240fa4ca66ab503effe7ad653c552cfe608e662e18e8ce5eb8),
36
- y: uint256(0x1b5829dbe6ee24d5f1a776ddc4e27a90888310a3f384fe8f70cd86c2f9eebf7e)
32
+ x: uint256(0x19d90118c106191d2f2f0350a56547c943c1ed5910d47dd067761099b54d11f3),
33
+ y: uint256(0x0f8f03c2def6108448f72f5177b6a2eed01250670efb63ea6f5ab65abc2a6885)
37
34
  }),
38
35
  qc: Honk.G1Point({
39
- x: uint256(0x2ccaa4f079bfc85f3887807ba17bffd69c73402d557395f6730d31cf1f208e53),
40
- y: uint256(0x11e38adba343d4c9839c5b4ed4d54c38d7d0e17b0c3890add1544aa18a53f805)
36
+ x: uint256(0x2ead500c79e717f5cdbba88ffef46477c4f30926bf59547a9c141c4158f7c843),
37
+ y: uint256(0x027d6b571b395cf61aae9626f172ce4e41e598456f7b8e535c027e9129b2c98e)
41
38
  }),
42
39
  qLookup: Honk.G1Point({
43
- x: uint256(0x111ada27d4243c5df982e1cd77f2d9aff394ba4f2ba2faf8ec1a8e5b6d78d1e7),
44
- y: uint256(0x1cf81a5fe339ef18222213e43155e149d0211317fe0a68d795681f31ef25ad0f)
40
+ x: uint256(0x136236e1bfc2af648ac078e134c1b4b9114b11937ebafcdd87f8ca7660715ebb),
41
+ y: uint256(0x02293c705250462935a653b7b993e13e2e8bc6480c45c84976d526cbdbd071df)
45
42
  }),
46
43
  qArith: Honk.G1Point({
47
- x: uint256(0x2771f716f503f8552b69271a62ec8cd7ab492b67f4859d8ff0321ce075e0361e),
48
- y: uint256(0x0a7762803ccc6145a73d9df81cb83b8d7125f07f998525b8ec888bb39ff32658)
44
+ x: uint256(0x074e7ead679c76d2c2d6d3f158cb522e71d14a169b2b1d0792cdfdad726f17a4),
45
+ y: uint256(0x21f9acd78d4150858f29c259c07e4552f6ec4bffac6c1e174cfb90e2e26bd68a)
49
46
  }),
50
47
  qDeltaRange: Honk.G1Point({
51
- x: uint256(0x0188abc30c433d60b371a87b89bef69474c4de9748b2b4b4e01d3e423cc2e975),
52
- y: uint256(0x2bbddad8b0e16ca7d71b0ca54b0f6251ea7c4457d76ba3327982171026423a40)
48
+ x: uint256(0x0cebfba75751a4eff3d7855bf0f314e523e2c709a75992eb5674a546627248e3),
49
+ y: uint256(0x16b715150f4de399940c535932174f5c634c9fd9137a94008bb38f89f1350b4c)
53
50
  }),
54
51
  qElliptic: Honk.G1Point({
55
- x: uint256(0x1a2e2850cfbe3912c8f6a4c0099bc93bc50841ce22d665b83b081753ce664a24),
56
- y: uint256(0x1976524b69c879a83c4d704ff5cb39397679528681ad378e6753e8b63457c40e)
52
+ x: uint256(0x174dba7fa4e38a55a78e43dda6c3fb81a1293285cf33eeb333ee186bb4331563),
53
+ y: uint256(0x0a2ff722359e35596e5abeec834c6cd73f4b06f5f2e837b31364f199f449ca77)
57
54
  }),
58
55
  qMemory: Honk.G1Point({
59
- x: uint256(0x2e569e263fc7a1cfa7b839e1d01a24bb6e07a396cbe93280eaa5f428f9bfcda3),
60
- y: uint256(0x232683b772e71e0839c2c22a0325540c142df09d86ad281e95c9a8526c8a8b1d)
56
+ x: uint256(0x29f116092db8eb3773b017110ca5d3a7b35fa1b064cde91c9e280e20399d7ec2),
57
+ y: uint256(0x1f0e39e18ded75167a270d6e31b9a6ad9a9d1b0d67c365eeb172a3fea4d1371e)
61
58
  }),
62
59
  qNnf: Honk.G1Point({
63
- x: uint256(0x21cdfcabf16e6fa296718413cc974b48e44c715143907a9c5cc722aa737b74b0),
64
- y: uint256(0x2280bd00b21340373b65aa88a619fa5f770435b772e1620701f76d769d041ea4)
60
+ x: uint256(0x19da50fca27dd36a006892b7cb6b36d7cfdac9d65fec6ae7a1a2e092e0988de5),
61
+ y: uint256(0x08f96f1d8e37be6dc83c9fbb3b912493841e4e81ab28a60c0fc85337cc4ed977)
65
62
  }),
66
63
  qPoseidon2External: Honk.G1Point({
67
- x: uint256(0x0e5cb0521c16b7e51540251b51adb95e4ce6d507a75c32e0c33377c21853d058),
68
- y: uint256(0x2ca91c89d04305640dcd8eefc8d33d78d27efee8fda3ac261150c8d675dff0d3)
64
+ x: uint256(0x2d20446a333063e66c1a552fecdfe12d0fdddeef0034569ac350f3299b09955a),
65
+ y: uint256(0x175e6e8776625134217ce9516a11cbbeab8c4c1c8b41cfb75f43de1f500b07d2)
69
66
  }),
70
67
  qPoseidon2Internal: Honk.G1Point({
71
- x: uint256(0x1e7842d12cae260b5fabe275ae67fc449e3a55615f7f83da87b1ea7c9e8f0500),
72
- y: uint256(0x1ea86788529c46dc304e64c22662f3c8c4e3e2e347500ccf539780071a293aad)
68
+ x: uint256(0x090a76cca3c754a2ba40abdc2572fff64645060cfa5c48239a1df4dbb8360828),
69
+ y: uint256(0x0499d4c6aed1f78b33a6701459cd069e9bf7262754d2f15074a6c2401950761f)
73
70
  }),
74
71
  s1: Honk.G1Point({
75
- x: uint256(0x0e90e964ef25f8c1aec26541f31cc9320b50fd36e39520d025d13e032037727e),
76
- y: uint256(0x1089017a718fae9b93f24789f8ef17aeed176bf9d16edb535a63d32648528a92)
72
+ x: uint256(0x012609fcd0fa67214d78f2d5f5e3e2b459a3c4b21531646de7d51d9cd5383aa9),
73
+ y: uint256(0x21394cebbe5f66f3aecf43d318b3cb9fc7640825baba0c5a5c190a20ceeb5edb)
77
74
  }),
78
75
  s2: Honk.G1Point({
79
- x: uint256(0x1aacf9506f5763680928c04b60d8217d4db189f8e148fd444a114ea18338fc8c),
80
- y: uint256(0x0b260dbc5d61e1b32e055570a5dd0a835b4f9672cd12dad8314aaa58eea62dd4)
76
+ x: uint256(0x080c7f024d9c813c60c84fc3e9bcad553c51f276d55e8d7a03c044b41cedef36),
77
+ y: uint256(0x2109db10b2da84ec2c4a1b62689d0952ababe94915293dfee09f1083010e5cfb)
81
78
  }),
82
79
  s3: Honk.G1Point({
83
- x: uint256(0x00357d87f2822ca4102863d9736d121154762e65008fb88d0851b22f7d564c5f),
84
- y: uint256(0x261b2a08cf2c8f3df7c5758aa7532df230d3348c1ad7b6ff1cf75dce3e8a03c7)
80
+ x: uint256(0x2f7d6b77cd5c3ee56c255be61d0e90fd7da5898a7ce4850aaf1060513cb7cd9d),
81
+ y: uint256(0x2ce5fdacbf91fc3358f4eba637d60f109f70fa929a6a1bc1f9d86e7856b87dcd)
85
82
  }),
86
83
  s4: Honk.G1Point({
87
- x: uint256(0x063add626791aade9be4f0371c6bb601295f7715cd35c540a64881892bb9015f),
88
- y: uint256(0x242cfc11084db62679ffc86ae33655c2adf2c60ee9a18c3fda51910194358f18)
84
+ x: uint256(0x1db1540beb4dc13e8519b82205e9b4cb48833040c8b322d626df57e078afecc4),
85
+ y: uint256(0x28eb12f9f02ac092326277365f9eeaff536b8dbf771f9ace22d0e122f922196a)
89
86
  }),
90
87
  t1: Honk.G1Point({
91
88
  x: uint256(0x1f16b037f0b4c96ea2a30a118a44e139881c0db8a4d6c9fde7db5c1c1738e61f),
@@ -104,28 +101,28 @@ library HonkVerificationKey {
104
101
  y: uint256(0x2d7e8c1ecb92e2490049b50efc811df63f1ca97e58d5e82852dbec0c29715d71)
105
102
  }),
106
103
  id1: Honk.G1Point({
107
- x: uint256(0x1dab2791b5e739b6eda84ec6578132dd1f9295f16540f1a221a615f137c750d0),
108
- y: uint256(0x0be694840789fada394fb3182a06d50f0c313775cea2b52e6ec3d09705d4ed13)
104
+ x: uint256(0x0a10b2e79989b15e3a69bd491cdae007b0bf9c82d9be3d7867b33e2287b91dac),
105
+ y: uint256(0x257794eaba7a0e7aed16e03d4d8c4cf7d878b029f4ea45c559bbc19b5ec4d1de)
109
106
  }),
110
107
  id2: Honk.G1Point({
111
- x: uint256(0x2922506083c612268913dac1af860cae5d49406ce01679ccfc17f95f1ab2a95f),
112
- y: uint256(0x29b3e2aa20c02de724c5142a941fdc7578c80fa8e2984882ffdf2c3a98ab8877)
108
+ x: uint256(0x25791b725ea7c712316ac4ffe10fdfcf37bd2b8f9d730ba2e26fa709bc7c3ae0),
109
+ y: uint256(0x15fba3e7928d36dc4dd6d6ff198b928c7246310974d4f74161cfd2781b9d3686)
113
110
  }),
114
111
  id3: Honk.G1Point({
115
- x: uint256(0x021afc0b974f923bb6e3116b7a7d04af835678e17a0e8ef3e9e723ca2c2122e9),
116
- y: uint256(0x1a1a18df93aba1975b374fd27695da35bbc0e243edbbcf67ec6e58c3441198fb)
112
+ x: uint256(0x270be32427e6404801b9b014f983d80acf18b828c6cf049f430d98fbe34e85e0),
113
+ y: uint256(0x2e7d27a99c4b574557ea6117c390c65072cdfa51a08621141ae26d7e143d0669)
117
114
  }),
118
115
  id4: Honk.G1Point({
119
- x: uint256(0x22c8713ddae54a7bb0751e8e2d97049735a71cf2e840c5a8c4e3d94af4bad28b),
120
- y: uint256(0x12b05267a7d72d33761c4742e8b03365cbdb383efd91743447b64d1714259595)
116
+ x: uint256(0x18e2902febdb3e45358fe65981f338a7ffd1b16edd917de670fabe5d15307e20),
117
+ y: uint256(0x2f6f36f307a0f7012dc3918795312e71a1d4752966c2bc3151e5f5b3151fc236)
121
118
  }),
122
119
  lagrangeFirst: Honk.G1Point({
123
120
  x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001),
124
121
  y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002)
125
122
  }),
126
123
  lagrangeLast: Honk.G1Point({
127
- x: uint256(0x23322d7d1115f6d1ee1e781cf348e56fbdf96c6853625397732a472b0711fa65),
128
- y: uint256(0x0359cc7c66a45d683d935dfaac2ada72634fd94dec1136ddf9dda711219be516)
124
+ x: uint256(0x12b14f226e24a52e0bc85bc5478c806023107f257430aae49136064dd3315c60),
125
+ y: uint256(0x0dfe490435cf839caf81df5c8a164afc5e3c8646f36bf27c19850b3f913edce4)
129
126
  })
130
127
  });
131
128
  return vk;
@@ -13,6 +13,34 @@ contract MockEnclave {
13
13
  bytes public plaintextOutput;
14
14
  bytes32 public committeePublicKey;
15
15
 
16
+ uint256 public nextE3Id;
17
+
18
+ mapping(uint256 => E3) public e3s;
19
+
20
+ function request(address program) external {
21
+ e3s[nextE3Id] = E3({
22
+ seed: 0,
23
+ threshold: [uint32(1), uint32(2)],
24
+ requestBlock: 0,
25
+ startWindow: [uint256(0), uint256(0)],
26
+ duration: 0,
27
+ expiration: 0,
28
+ encryptionSchemeId: bytes32(0),
29
+ e3Program: IE3Program(program),
30
+ e3ProgramParams: bytes(""),
31
+ customParams: abi.encode(address(0), nextE3Id, 2, 0, 0),
32
+ decryptionVerifier: IDecryptionVerifier(address(0)),
33
+ committeePublicKey: committeePublicKey,
34
+ ciphertextOutput: bytes32(0),
35
+ plaintextOutput: plaintextOutput,
36
+ requester: address(0)
37
+ });
38
+
39
+ IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), abi.encode(address(0), nextE3Id, 2));
40
+
41
+ nextE3Id++;
42
+ }
43
+
16
44
  function setPlaintextOutput(bytes memory plaintext) external {
17
45
  plaintextOutput = plaintext;
18
46
  }
@@ -21,7 +49,7 @@ contract MockEnclave {
21
49
  committeePublicKey = publicKeyHash;
22
50
  }
23
51
 
24
- function getE3(uint256 e3Id) external view returns (E3 memory) {
52
+ function getE3(uint256) external view returns (E3 memory) {
25
53
  return
26
54
  E3({
27
55
  seed: 0,
@@ -33,7 +61,7 @@ contract MockEnclave {
33
61
  encryptionSchemeId: bytes32(0),
34
62
  e3Program: IE3Program(address(0)),
35
63
  e3ProgramParams: bytes(""),
36
- customParams: bytes(""),
64
+ customParams: abi.encode(address(0), 0, 2, 0, 0),
37
65
  decryptionVerifier: IDecryptionVerifier(address(0)),
38
66
  committeePublicKey: committeePublicKey,
39
67
  ciphertextOutput: bytes32(0),
@@ -0,0 +1,34 @@
1
+ // SPDX-License-Identifier: LGPL-3.0-only
2
+ //
3
+ // This file is provided WITHOUT ANY WARRANTY;
4
+ // without even the implied warranty of MERCHANTABILITY
5
+ // or FITNESS FOR A PARTICULAR PURPOSE.
6
+ pragma solidity ^0.8.27;
7
+
8
+ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
9
+
10
+ /// @title MockVotingToken
11
+ /// @notice A mock voting token for testing purposes
12
+ /// @dev Public mint function that allows to keep balances to 1e9.
13
+ /// @dev by default CRISP server will scale down voting power by 1e18/2
14
+ /// @dev in this case leaving everyone with a balance of 1 to vote yes or no
15
+ contract MockVotingToken is ERC20 {
16
+ // half of 10e18
17
+ uint256 public constant MAX_BALANCE = 1e9;
18
+
19
+ constructor() ERC20("Mock Voting Token", "MVT") {
20
+ _mint(msg.sender, 1e9);
21
+ }
22
+
23
+ function mint(address to, uint256) external {
24
+ if (balanceOf(to) + 1e9 > MAX_BALANCE) {
25
+ // silently fail
26
+ return;
27
+ }
28
+ _mint(to, 1e9);
29
+ }
30
+
31
+ function decimals() public pure override returns (uint8) {
32
+ return 18;
33
+ }
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crisp-e3/contracts",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "contracts",
@@ -31,7 +31,7 @@
31
31
  "@zk-kit/lazy-imt.sol": "2.0.0-beta.12",
32
32
  "poseidon-solidity": "^0.0.5",
33
33
  "solady": "^0.1.13",
34
- "@enclave-e3/contracts": "0.1.7"
34
+ "@enclave-e3/contracts": "0.1.8"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@nomicfoundation/hardhat-ethers": "4",
@@ -59,8 +59,8 @@
59
59
  "typechain": "^8.3.0",
60
60
  "typescript": "5.8.3",
61
61
  "viem": "2.30.6",
62
- "@crisp-e3/sdk": "^0.5.8",
63
- "@crisp-e3/zk-inputs": "^0.5.8"
62
+ "@crisp-e3/zk-inputs": "^0.5.10",
63
+ "@crisp-e3/sdk": "^0.5.10"
64
64
  },
65
65
  "scripts": {
66
66
  "compile": "hardhat compile",
@@ -69,8 +69,9 @@
69
69
  "ciphernode:add:self": "hardhat ciphernode:add",
70
70
  "clean:deployments": "hardhat utils:clean-deployments",
71
71
  "deploy:contracts": "hardhat run deploy/deploy.ts",
72
+ "deploy:contracts:mock": "export USE_MOCKS=true PRINT_ENV_VARS=true && pnpm deploy:contracts",
72
73
  "deploy:contracts:full": "export DEPLOY_ENCLAVE=true && pnpm deploy:contracts",
73
- "deploy:contracts:full:mock": "export DEPLOY_ENCLAVE=true USE_MOCK_VERIFIER=true PRINT_ENV_VARS=true && pnpm deploy:contracts",
74
+ "deploy:contracts:full:mock": "export DEPLOY_ENCLAVE=true USE_MOCKS=true PRINT_ENV_VARS=true && pnpm deploy:contracts",
74
75
  "test": "hardhat test mocha",
75
76
  "verify": "hardhat run deploy/verify.ts",
76
77
  "updateSubmissionWindow": "hardhat ciphernode:window"