@silvana-one/upgradable 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.
@@ -0,0 +1,383 @@
1
+ import { Struct, Field, PublicKey, Signature, ZkProgram, Poseidon, SelfProof, UInt32, Experimental, DynamicProof, FeatureFlags, Bool, Nullifier, Provable, Encoding, } from "o1js";
2
+ import { Storage } from "@silvana-one/storage";
3
+ import { PublicKeyOption } from "./upgradable.js";
4
+ import MinaSigner from "mina-signer";
5
+ export { ValidatorsList, UpgradeAuthorityDatabase, ValidatorsState, ValidatorsDecision, ValidatorDecisionType, ValidatorsDecisionState, ValidatorsVoting, ValidatorsVotingProof, ValidatorsVotingNativeProof, UpgradeDatabaseState, UpgradeDatabaseStatePacked, ChainId, };
6
+ const { IndexedMerkleMap } = Experimental;
7
+ const VALIDATORS_LIST_HEIGHT = 10;
8
+ const UPGRADE_AUTHORITY_DATABASE_HEIGHT = 20;
9
+ /**
10
+ * The `ValidatorsList` is an indexed Merkle map used to store the list of validators.
11
+ */
12
+ class ValidatorsList extends IndexedMerkleMap(VALIDATORS_LIST_HEIGHT) {
13
+ }
14
+ /**
15
+ * The `UpgradeAuthorityDatabase` is an indexed Merkle map used to manage upgrade proposals.
16
+ */
17
+ class UpgradeAuthorityDatabase extends IndexedMerkleMap(UPGRADE_AUTHORITY_DATABASE_HEIGHT) {
18
+ }
19
+ /** Chain IDs following Auro Wallet naming conventions. */
20
+ const ChainId = {
21
+ "mina:mainnet": fieldFromString("mina:mainnet"),
22
+ "mina:devnet": fieldFromString("mina:devnet"),
23
+ "zeko:mainnet": fieldFromString("zeko:mainnet"),
24
+ "zeko:devnet": fieldFromString("zeko:devnet"),
25
+ };
26
+ /** Validator decision types for upgrade proposals. */
27
+ const ValidatorDecisionType = {
28
+ updateDatabase: fieldFromString("updateDatabase"),
29
+ updateValidatorsList: fieldFromString("updateValidatorsList"),
30
+ };
31
+ /**
32
+ * Represents the state of the validators.
33
+ */
34
+ class ValidatorsState extends Struct({
35
+ /** Chain ID (e.g., 'mina:mainnet') */
36
+ chainId: Field,
37
+ /** Merkle root of the ValidatorsList */
38
+ root: Field,
39
+ /** Number of validators */
40
+ count: UInt32,
41
+ }) {
42
+ /**
43
+ * Asserts that two `ValidatorsState` instances are equal.
44
+ * @param a First `ValidatorsState` instance.
45
+ * @param b Second `ValidatorsState` instance.
46
+ */
47
+ static assertEquals(a, b) {
48
+ a.chainId.assertEquals(b.chainId);
49
+ a.root.assertEquals(b.root);
50
+ a.count.assertEquals(b.count);
51
+ }
52
+ /**
53
+ * Computes the hash of the validators state.
54
+ * @returns Hash of the current state.
55
+ */
56
+ hash() {
57
+ return Poseidon.hashPacked(ValidatorsState, this);
58
+ }
59
+ /**
60
+ * Returns an empty `ValidatorsState`.
61
+ * @returns An empty `ValidatorsState` instance.
62
+ */
63
+ static empty() {
64
+ return new ValidatorsState({
65
+ chainId: Field(0),
66
+ root: Field(0),
67
+ count: UInt32.zero,
68
+ });
69
+ }
70
+ }
71
+ /**
72
+ * Represents the packed state of the upgrade database.
73
+ */
74
+ class UpgradeDatabaseStatePacked extends Struct({
75
+ /** Root of the UpgradeAuthority database */
76
+ root: Field,
77
+ /** Storage information (e.g., IPFS hash) */
78
+ storage: Storage,
79
+ /** X-coordinate of the next upgrade authority's public key */
80
+ nextUpgradeAuthorityX: Field,
81
+ /** Packed data containing version, validFrom, and flags */
82
+ data: Field,
83
+ }) {
84
+ }
85
+ /**
86
+ * Represents the state of the upgrade database.
87
+ */
88
+ class UpgradeDatabaseState extends Struct({
89
+ /** Root of the UpgradeAuthority database */
90
+ root: Field,
91
+ /** Storage information (e.g., IPFS hash) */
92
+ storage: Storage,
93
+ /** Optional public key of the next upgrade authority */
94
+ nextUpgradeAuthority: PublicKeyOption,
95
+ /** Version of the UpgradeAuthorityDatabase */
96
+ version: UInt32,
97
+ /** Slot when the UpgradeAuthority is valid from */
98
+ validFrom: UInt32,
99
+ }) {
100
+ /**
101
+ * Asserts that two `UpgradeDatabaseState` instances are equal.
102
+ * @param a First `UpgradeDatabaseState` instance.
103
+ * @param b Second `UpgradeDatabaseState` instance.
104
+ */
105
+ static assertEquals(a, b) {
106
+ a.root.assertEquals(b.root);
107
+ Storage.assertEquals(a.storage, b.storage);
108
+ a.nextUpgradeAuthority.value.assertEquals(b.nextUpgradeAuthority.value);
109
+ a.nextUpgradeAuthority.isSome.assertEquals(b.nextUpgradeAuthority.isSome);
110
+ a.version.assertEquals(b.version);
111
+ }
112
+ /**
113
+ * Returns an empty `UpgradeDatabaseState`.
114
+ * @returns An empty `UpgradeDatabaseState` instance.
115
+ */
116
+ static empty() {
117
+ return new UpgradeDatabaseState({
118
+ root: new UpgradeAuthorityDatabase().root,
119
+ storage: Storage.empty(),
120
+ nextUpgradeAuthority: PublicKeyOption.none(),
121
+ version: UInt32.zero,
122
+ validFrom: UInt32.MAXINT(),
123
+ });
124
+ }
125
+ /**
126
+ * Packs the `UpgradeDatabaseState` into a `UpgradeDatabaseStatePacked`.
127
+ * @returns A packed representation of the upgrade database state.
128
+ */
129
+ pack() {
130
+ const nextUpgradeAuthorityX = this.nextUpgradeAuthority.value.x;
131
+ const data = Field.fromBits([
132
+ ...this.version.value.toBits(32),
133
+ ...this.validFrom.value.toBits(32),
134
+ this.nextUpgradeAuthority.value.isOdd,
135
+ this.nextUpgradeAuthority.isSome,
136
+ ]);
137
+ return new UpgradeDatabaseStatePacked({
138
+ root: this.root,
139
+ storage: this.storage,
140
+ nextUpgradeAuthorityX,
141
+ data,
142
+ });
143
+ }
144
+ /**
145
+ * Unpacks a `UpgradeDatabaseStatePacked` into a `UpgradeDatabaseState`.
146
+ * @param packed The packed upgrade database state.
147
+ * @returns An unpacked `UpgradeDatabaseState` instance.
148
+ */
149
+ static unpack(packed) {
150
+ const bits = packed.data.toBits(66);
151
+ const versionBits = bits.slice(0, 32);
152
+ const validFromBits = bits.slice(32, 64);
153
+ const isOddBit = bits[64];
154
+ const isSomeBit = bits[65];
155
+ const version = UInt32.Unsafe.fromField(Field.fromBits(versionBits));
156
+ const validFrom = UInt32.Unsafe.fromField(Field.fromBits(validFromBits));
157
+ const nextUpgradeAuthority = PublicKeyOption.from(PublicKey.from({ x: packed.nextUpgradeAuthorityX, isOdd: isOddBit }));
158
+ nextUpgradeAuthority.isSome = isSomeBit;
159
+ return new UpgradeDatabaseState({
160
+ root: packed.root,
161
+ storage: packed.storage,
162
+ nextUpgradeAuthority,
163
+ version,
164
+ validFrom,
165
+ });
166
+ }
167
+ }
168
+ /**
169
+ * Represents a decision made by the validators.
170
+ */
171
+ class ValidatorsDecision extends Struct({
172
+ /** Message to be signed when producing the nullifier, also serves as the nonce to prevent replay attacks */
173
+ message: Field,
174
+ /** Type of decision (e.g., 'updateDatabase') */
175
+ decisionType: Field,
176
+ /** UpgradeAuthority contract address */
177
+ contractAddress: PublicKey,
178
+ /** Chain ID */
179
+ chainId: Field,
180
+ /** Current validators state */
181
+ validators: ValidatorsState,
182
+ /** Current upgrade database state */
183
+ upgradeDatabase: UpgradeDatabaseState,
184
+ /** Proposed update to validators state */
185
+ updateValidatorsList: ValidatorsState,
186
+ /** Slot when decision expires */
187
+ expiry: UInt32,
188
+ }) {
189
+ /**
190
+ * Asserts that two `ValidatorsDecision` instances are equal.
191
+ * @param a First `ValidatorsDecision` instance.
192
+ * @param b Second `ValidatorsDecision` instance.
193
+ */
194
+ static assertEquals(a, b) {
195
+ a.message.assertEquals(b.message);
196
+ a.decisionType.assertEquals(b.decisionType);
197
+ a.contractAddress.assertEquals(b.contractAddress);
198
+ a.chainId.assertEquals(b.chainId);
199
+ ValidatorsState.assertEquals(a.validators, b.validators);
200
+ UpgradeDatabaseState.assertEquals(a.upgradeDatabase, b.upgradeDatabase);
201
+ a.expiry.assertEquals(b.expiry);
202
+ }
203
+ createNullifierMessage() {
204
+ return [this.message, ...ValidatorsDecision.toFields(this)];
205
+ }
206
+ createJsonNullifier(params) {
207
+ const { network, privateKey } = params;
208
+ const minaSigner = new MinaSigner({ network });
209
+ const message = this.createNullifierMessage();
210
+ const nullifier = minaSigner.createNullifier(message.map((field) => field.toBigInt()), privateKey.toBase58());
211
+ return nullifier;
212
+ }
213
+ }
214
+ /**
215
+ * Represents the state of a validators decision during the voting process.
216
+ */
217
+ class ValidatorsDecisionState extends Struct({
218
+ /** The validators' decision */
219
+ decision: ValidatorsDecision,
220
+ /** Indexed Merkle Map root of the validators who have voted */
221
+ alreadyVoted: Field,
222
+ /** Number of votes in favor of the decision */
223
+ yesVotes: UInt32,
224
+ /** Number of votes against the decision */
225
+ noVotes: UInt32,
226
+ /** Number of votes of abstention */
227
+ abstainVotes: UInt32,
228
+ }) {
229
+ static startVoting(decision) {
230
+ return new ValidatorsDecisionState({
231
+ decision,
232
+ alreadyVoted: new ValidatorsList().root,
233
+ yesVotes: UInt32.zero,
234
+ noVotes: UInt32.zero,
235
+ abstainVotes: UInt32.zero,
236
+ });
237
+ }
238
+ /**
239
+ * Records a vote
240
+ * @param validatorNullifier The nullifier of the validator.
241
+ * @param validatorsList The ValidatorsList containing authorized validators.
242
+ * @param votedList The ValidatorsList tracking who has already voted.
243
+ * @param yes Whether this is a "yes" vote.
244
+ * @param no Whether this is a "no" vote.
245
+ * @param abstain Whether this is an "abstain" vote.
246
+ * @param signature The signature of the validator.
247
+ * @returns A new `ValidatorsDecisionState` reflecting the vote.
248
+ */
249
+ vote(validatorNullifier, validatorsList, votedList, yes, no, abstain, signature) {
250
+ const publicKey = validatorNullifier.getPublicKey();
251
+ const key = validatorNullifier.key();
252
+ validatorNullifier.verify(this.decision.createNullifierMessage());
253
+ const previousVotesCount = this.yesVotes
254
+ .add(this.noVotes)
255
+ .add(this.abstainVotes);
256
+ const yesVotes = this.yesVotes.add(Provable.if(yes, UInt32.from(1), UInt32.from(0)));
257
+ const noVotes = this.noVotes.add(Provable.if(no, UInt32.from(1), UInt32.from(0)));
258
+ const abstainVotes = this.abstainVotes.add(Provable.if(abstain, UInt32.from(1), UInt32.from(0)));
259
+ // Ensure exactly one vote type is selected
260
+ previousVotesCount
261
+ .add(UInt32.from(1))
262
+ .assertEquals(yesVotes.add(noVotes).add(abstainVotes));
263
+ const hash = Poseidon.hashPacked(PublicKey, publicKey);
264
+ validatorsList.root.assertEquals(this.decision.validators.root);
265
+ validatorsList
266
+ .get(hash)
267
+ .assertBool("Wrong ValidatorsList format")
268
+ .assertTrue("Validator doesn't have authority to sign");
269
+ signature
270
+ .verify(publicKey, ValidatorsDecision.toFields(this.decision))
271
+ .assertTrue("Wrong validator signature");
272
+ this.decision.validators.root.assertEquals(validatorsList.root);
273
+ votedList.root.assertEquals(this.alreadyVoted);
274
+ votedList.insert(key, Field(1));
275
+ return new ValidatorsDecisionState({
276
+ decision: this.decision,
277
+ alreadyVoted: votedList.root,
278
+ yesVotes,
279
+ noVotes,
280
+ abstainVotes,
281
+ });
282
+ }
283
+ /**
284
+ * Asserts that two `ValidatorsDecisionState` instances are equal.
285
+ * @param a First `ValidatorsDecisionState` instance.
286
+ * @param b Second `ValidatorsDecisionState` instance.
287
+ */
288
+ static assertEquals(a, b) {
289
+ ValidatorsDecision.assertEquals(a.decision, b.decision);
290
+ a.alreadyVoted.assertEquals(b.alreadyVoted);
291
+ a.yesVotes.assertEquals(b.yesVotes);
292
+ a.noVotes.assertEquals(b.noVotes);
293
+ a.abstainVotes.assertEquals(b.abstainVotes);
294
+ }
295
+ }
296
+ /**
297
+ * The `ValidatorsVoting` ZkProgram implements the voting logic for validators.
298
+ */
299
+ const ValidatorsVoting = ZkProgram({
300
+ name: "ValidatorsVoting",
301
+ publicInput: ValidatorsDecisionState,
302
+ publicOutput: ValidatorsDecisionState,
303
+ methods: {
304
+ /**
305
+ * Starts the voting process for a decision.
306
+ */
307
+ startVoting: {
308
+ privateInputs: [ValidatorsDecision],
309
+ async method(state, decision) {
310
+ const calculatedState = ValidatorsDecisionState.startVoting(decision);
311
+ ValidatorsDecisionState.assertEquals(state, calculatedState);
312
+ return { publicOutput: calculatedState };
313
+ },
314
+ },
315
+ /**
316
+ * Records a vote
317
+ */
318
+ vote: {
319
+ privateInputs: [
320
+ ValidatorsDecision,
321
+ Nullifier,
322
+ ValidatorsList,
323
+ ValidatorsList,
324
+ Bool,
325
+ Bool,
326
+ Bool,
327
+ Signature,
328
+ ],
329
+ async method(state, decision, nullifier, validatorsList, votedList, yes, no, abstain, signature) {
330
+ const calculatedState = state.vote(nullifier, validatorsList, votedList, yes, no, abstain, signature);
331
+ return { publicOutput: calculatedState };
332
+ },
333
+ },
334
+ /**
335
+ * Merges two `ValidatorsDecisionState` proofs.
336
+ */
337
+ merge: {
338
+ privateInputs: [SelfProof, SelfProof],
339
+ async method(state, proof1, proof2) {
340
+ proof1.verify();
341
+ proof2.verify();
342
+ ValidatorsDecisionState.assertEquals(state, proof1.publicInput);
343
+ ValidatorsDecisionState.assertEquals(proof1.publicOutput, proof2.publicInput);
344
+ return { publicOutput: proof2.publicOutput };
345
+ },
346
+ },
347
+ },
348
+ });
349
+ /** Proof classes for the `ValidatorsVoting` ZkProgram. */
350
+ class ValidatorsVotingNativeProof extends ZkProgram.Proof(ValidatorsVoting) {
351
+ }
352
+ class ValidatorsVotingProof extends DynamicProof {
353
+ static { this.publicInputType = ValidatorsDecisionState; }
354
+ static { this.publicOutputType = ValidatorsDecisionState; }
355
+ static { this.maxProofsVerified = 2; }
356
+ static { this.featureFlags = FeatureFlags.allMaybe; }
357
+ }
358
+ /**
359
+ * Converts a `Field` element to a string representation.
360
+ * This is used for serializing `Field` values into strings suitable for storage or transmission.
361
+ *
362
+ * @param {Field} field - The `Field` element to convert.
363
+ * @returns {string} The string representation of the `Field`.
364
+ */
365
+ function fieldToString(field) {
366
+ return Encoding.stringFromFields([field]);
367
+ }
368
+ /**
369
+ * Reconstructs a `Field` element from its string representation.
370
+ * This function is essential for deserializing strings back into `Field` elements,
371
+ * which can then be used within the smart contract logic.
372
+ *
373
+ * @param {string} storage - The string representation of the `Field`.
374
+ * @returns {Field} The reconstructed `Field` element.
375
+ * @throws Will throw an error if the input string does not correspond to exactly one `Field`.
376
+ */
377
+ function fieldFromString(storage) {
378
+ const fields = Encoding.stringToFields(storage);
379
+ if (fields.length !== 1)
380
+ throw new Error("String is too long");
381
+ return fields[0];
382
+ }
383
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@silvana-one/upgradable",
3
+ "description": "Silvana Upgradable interface for Mina zkApps",
4
+ "version": "0.1.0",
5
+ "author": "DFST",
6
+ "bugs": "https://github.com/SilvanaOne/silvana-lib/issues",
7
+ "dependencies": {
8
+ "mina-signer": "^3.0.7",
9
+ "tslib": "^2.8.1"
10
+ },
11
+ "devDependencies": {
12
+ "@silvana-one/storage": "0.1.0",
13
+ "@types/node": "^22.10.2",
14
+ "esbuild": "^0.24.0",
15
+ "o1js": "^2.2.0",
16
+ "typescript": "^5.7.2"
17
+ },
18
+ "engines": {
19
+ "node": ">=20.0.0"
20
+ },
21
+ "exports": {
22
+ "types": "./dist/node/index.d.ts",
23
+ "node": {
24
+ "import": "./dist/node/index.js",
25
+ "require": "./dist/node/index.cjs"
26
+ },
27
+ "browser": "./dist/web/index.js",
28
+ "default": "./dist/web/index.js"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "src",
33
+ "package.json",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "homepage": "https://docs.silvana.one",
38
+ "keywords": [
39
+ "mina-protocol",
40
+ "typescript",
41
+ "Upgradable",
42
+ "zkApps"
43
+ ],
44
+ "license": "Apache-2.0",
45
+ "main": "dist/web/index.js",
46
+ "peerDependencies": {
47
+ "@silvana-one/storage": "0.1.0",
48
+ "o1js": "^2.2.0"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "repository": "SilvanaOne/silvana-lib.git",
54
+ "scripts": {
55
+ "build": "rm -rf dist && tsc && tsc --build tsconfig.web.json && node build-cjs.js",
56
+ "release": "npm publish --access public"
57
+ },
58
+ "type": "module",
59
+ "types": "./dist/node/index.d.ts"
60
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./validators.js";
2
+ export * from "./upgrade.js";
3
+ export * from "./upgradable.js";
@@ -0,0 +1,115 @@
1
+ import {
2
+ Bool,
3
+ PublicKey,
4
+ SmartContract,
5
+ VerificationKey,
6
+ Field,
7
+ Struct,
8
+ Poseidon,
9
+ Option,
10
+ } from "o1js";
11
+
12
+ export {
13
+ UpgradeAuthorityBase,
14
+ VerificationKeyUpgradeData,
15
+ UpgradeAuthorityContractConstructor,
16
+ UpgradableContract,
17
+ PublicKeyOption,
18
+ UpgradeAuthorityAnswer,
19
+ };
20
+
21
+ /**
22
+ * Represents the data required to upgrade a contract's verification key.
23
+ * It includes the contract's address, token ID, previous verification key hash,
24
+ * and the new verification key hash. This class also provides a `hash()` method
25
+ * to generate a unique identifier for the upgrade data.
26
+ */
27
+ class VerificationKeyUpgradeData extends Struct({
28
+ /** The address of the contract to be upgraded. */
29
+ address: PublicKey,
30
+ /** The token ID associated with the contract. */
31
+ tokenId: Field,
32
+ /** The hash of the previous verification key. */
33
+ previousVerificationKeyHash: Field,
34
+ /** The hash of the new verification key. */
35
+ newVerificationKeyHash: Field,
36
+ }) {
37
+ /**
38
+ * Generates a unique hash for the upgrade data using the Poseidon hash function.
39
+ * @returns {Field} The hash representing the upgrade data.
40
+ */
41
+ hash(): Field {
42
+ return Poseidon.hash(VerificationKeyUpgradeData.toFields(this));
43
+ }
44
+ }
45
+
46
+ /**
47
+ * An optional `PublicKey` type, used to specify the next upgrade authority if needed.
48
+ * This is crucial when the current upgrade authority cannot be used in future upgrades
49
+ * due to changes in the o1js version or other factors.
50
+ */
51
+ class PublicKeyOption extends Option(PublicKey) {}
52
+
53
+ /**
54
+ * Represents the response from the upgrade authority after verifying the upgrade data.
55
+ * It contains the next upgrade authority's public key if a change is required, and a boolean
56
+ * indicating whether the upgrade data has been successfully verified.
57
+ */
58
+ class UpgradeAuthorityAnswer extends Struct({
59
+ /**
60
+ * The public key of the next upgrade authority, if a change is required.
61
+ *
62
+ * If we upgrade the verification key, we may not be able to use the same upgrade
63
+ * authority next time because the new o1js version can break the verification key
64
+ * of the upgrade authority too, and since the upgrade authority serves many
65
+ * contracts, it cannot be upgraded. In this case, we need to use another upgrade
66
+ * authority with the public key that will be provided in `nextUpgradeAuthority`.
67
+ */
68
+ nextUpgradeAuthority: PublicKeyOption,
69
+ /** Indicates whether the upgrade data has been successfully verified. */
70
+ isVerified: Bool,
71
+ }) {}
72
+
73
+ /**
74
+ * Interface that any upgrade authority contract should implement.
75
+ * Extends `SmartContract` and requires the implementation of the `verifyUpgradeData()` method,
76
+ * which takes `VerificationKeyUpgradeData` as input and returns an `UpgradeAuthorityAnswer`.
77
+ */
78
+ type UpgradeAuthorityBase = SmartContract & {
79
+ /**
80
+ * Verifies the upgrade data for upgrading a contract's verification key.
81
+ * @param {VerificationKeyUpgradeData} data - The data required for verification.
82
+ * @returns {Promise<UpgradeAuthorityAnswer>} The result of the verification.
83
+ */
84
+ verifyUpgradeData(
85
+ data: VerificationKeyUpgradeData
86
+ ): Promise<UpgradeAuthorityAnswer>;
87
+ };
88
+
89
+ /**
90
+ * Interface for contracts that can be upgraded.
91
+ * Extends `SmartContract` and requires methods to retrieve the associated upgrade authority contract
92
+ * and to upgrade the contract's verification key using the provided verification key.
93
+ */
94
+ type UpgradableContract = SmartContract & {
95
+ /**
96
+ * Retrieves the associated upgrade authority contract.
97
+ * @returns {Promise<UpgradeAuthorityBase>} The upgrade authority contract.
98
+ */
99
+ getUpgradeContract(): Promise<UpgradeAuthorityBase>;
100
+
101
+ /**
102
+ * Upgrades the contract's verification key using the provided verification key.
103
+ * @param {VerificationKey} vk - The new verification key.
104
+ * @returns {Promise<void>}
105
+ */
106
+ upgradeVerificationKey(vk: VerificationKey): Promise<void>;
107
+ };
108
+
109
+ /**
110
+ * Defines a constructor for contracts implementing `UpgradeAuthorityBase`,
111
+ * accepting an `upgradeAuthority` public key and returning an instance of `UpgradeAuthorityBase`.
112
+ */
113
+ type UpgradeAuthorityContractConstructor = new (
114
+ upgradeAuthority: PublicKey
115
+ ) => UpgradeAuthorityBase;