Skip to content

Commit 85fab88

Browse files
Add simulator package (#247)
1 parent 95515da commit 85fab88

File tree

103 files changed

+5470
-506
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+5470
-506
lines changed

biome.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"!**/tsconfig*.json",
1515
"!**/*.compact",
1616
"!**/artifacts/**/*",
17+
"!**/test-artifacts/**/*",
1718
"!**/coverage/**/*",
1819
"!**/dist/**/*",
1920
"!**/reports/**/*"

contracts/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@openzeppelin-compact/compact": "workspace:^"
3030
},
3131
"devDependencies": {
32+
"@openzeppelin-compact/contracts-simulator": "workspace:^",
3233
"@tsconfig/node22": "^22.0.2",
3334
"@types/node": "22.18.0",
3435
"ts-node": "^10.9.2",

contracts/src/access/test/ZOwnablePK.test.ts

Lines changed: 24 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import {
33
CompactTypeVector,
44
convert_bigint_to_Uint8Array,
55
persistentHash,
6-
transientHash,
7-
upgradeFromTransient,
86
} from '@midnight-ntwrk/compact-runtime';
97
import { beforeEach, describe, expect, it } from 'vitest';
108
import type { ZswapCoinPublicKey } from '../../../artifacts/MockOwnable/contract/index.cjs';
@@ -101,7 +99,7 @@ describe('ZOwnablePK', () => {
10199
});
102100
});
103101

104-
describe('when not deployed and not initialized', () => {
102+
describe('when not initialized correctly', () => {
105103
const isNotInit = false;
106104

107105
beforeEach(() => {
@@ -138,36 +136,6 @@ describe('ZOwnablePK', () => {
138136
});
139137
});
140138

141-
describe('when incorrect hashing algo (not SHA256) is used to generate initial owner id', () => {
142-
// ZOwnablePK only supports sha256 for owner id calculation
143-
// Obviously, using any other algo for the id will not work
144-
const badHashAlgo = (pk: ZswapCoinPublicKey, nonce: Uint8Array) => {
145-
const rt_type = new CompactTypeVector(2, new CompactTypeBytes(32));
146-
return upgradeFromTransient(transientHash(rt_type, [pk.bytes, nonce]));
147-
};
148-
const secretNonce = ZOwnablePKPrivateState.generate().secretNonce;
149-
const badOwnerId = badHashAlgo(Z_OWNER, secretNonce);
150-
151-
beforeEach(() => {
152-
ownable = new ZOwnablePKSimulator(badOwnerId, INSTANCE_SALT, isInit);
153-
});
154-
//
155-
type FailingCircuits = [method: keyof ZOwnablePKSimulator, args: unknown[]];
156-
const protectedCircuits: FailingCircuits[] = [
157-
['assertOnlyOwner', []],
158-
['transferOwnership', [badOwnerId]],
159-
['renounceOwnership', []],
160-
];
161-
162-
it.each(protectedCircuits)('%s should fail', (circuitName, args) => {
163-
ownable.callerCtx.setCaller(OWNER);
164-
165-
expect(() => {
166-
(ownable[circuitName] as (...args: unknown[]) => unknown)(...args);
167-
}).toThrow('ZOwnablePK: caller is not the owner');
168-
});
169-
});
170-
171139
describe('after initialization', () => {
172140
beforeEach(() => {
173141
// Create private state object and generate nonce
@@ -216,40 +184,34 @@ describe('ZOwnablePK', () => {
216184
});
217185

218186
it('should transfer ownership', () => {
219-
ownable.callerCtx.setCaller(OWNER);
220-
ownable.transferOwnership(newIdHash);
187+
ownable.as(OWNER).transferOwnership(newIdHash);
221188
expect(ownable.owner()).toEqual(newOwnerCommitment);
222189

223190
// Old owner
224-
ownable.callerCtx.setCaller(OWNER);
225191
expect(() => {
226-
ownable.assertOnlyOwner();
192+
ownable.as(OWNER).assertOnlyOwner();
227193
}).toThrow('ZOwnablePK: caller is not the owner');
228194

229195
// Unauthorized
230-
ownable.callerCtx.setCaller(UNAUTHORIZED);
231196
expect(() => {
232-
ownable.assertOnlyOwner();
197+
ownable.as(UNAUTHORIZED).assertOnlyOwner();
233198
}).toThrow('ZOwnablePK: caller is not the owner');
234199

235200
// New owner
236-
ownable.callerCtx.setCaller(NEW_OWNER);
237201
ownable.privateState.injectSecretNonce(Buffer.from(newOwnerNonce));
238-
expect(ownable.assertOnlyOwner()).not.to.throw;
202+
expect(ownable.as(NEW_OWNER).assertOnlyOwner()).not.to.throw;
239203
});
240204

241205
it('should fail when transferring to id zero', () => {
242-
ownable.callerCtx.setCaller(OWNER);
243206
const badId = new Uint8Array(32).fill(0);
244207
expect(() => {
245-
ownable.transferOwnership(badId);
208+
ownable.as(OWNER).transferOwnership(badId);
246209
}).toThrow('ZOwnablePK: invalid id');
247210
});
248211

249212
it('should fail when unauthorized transfers ownership', () => {
250-
ownable.callerCtx.setCaller(UNAUTHORIZED);
251213
expect(() => {
252-
ownable.transferOwnership(newOwnerCommitment);
214+
ownable.as(UNAUTHORIZED).transferOwnership(newOwnerCommitment);
253215
}).toThrow('ZOwnablePK: caller is not the owner');
254216
});
255217

@@ -260,8 +222,7 @@ describe('ZOwnablePK', () => {
260222
const beforeInstance = ownable.getPublicState().ZOwnablePK__counter;
261223

262224
// Transfer
263-
ownable.callerCtx.setCaller(OWNER);
264-
ownable.transferOwnership(newOwnerCommitment);
225+
ownable.as(OWNER).transferOwnership(newOwnerCommitment);
265226

266227
// Check counter
267228
const afterInstance = ownable.getPublicState().ZOwnablePK__counter;
@@ -280,8 +241,7 @@ describe('ZOwnablePK', () => {
280241
expect(initCommitment).toEqual(expInitCommitment);
281242

282243
// Transfer ownership to self with the same id -> `H(pk, nonce)`
283-
ownable.callerCtx.setCaller(OWNER);
284-
ownable.transferOwnership(repeatedId);
244+
ownable.as(OWNER).transferOwnership(repeatedId);
285245

286246
// Check commitments don't match
287247
const newCommitment = ownable.owner();
@@ -297,46 +257,41 @@ describe('ZOwnablePK', () => {
297257
expect(newCommitment).toEqual(expNewCommitment);
298258

299259
// Check same owner maintains permissions after transfer
300-
ownable.callerCtx.setCaller(OWNER);
301-
expect(ownable.assertOnlyOwner()).not.to.throw;
260+
expect(ownable.as(OWNER).assertOnlyOwner()).not.to.throw;
302261
});
303262
});
304263

305264
describe('renounceOwnership', () => {
306265
it('should renounce ownership', () => {
307-
ownable.callerCtx.setCaller(OWNER);
308-
ownable.renounceOwnership();
266+
ownable.as(OWNER).renounceOwnership();
309267

310268
// Check owner is reset
311269
expect(ownable.owner()).toEqual(new Uint8Array(32).fill(0));
312270

313271
// Check revoked permissions
314272
expect(() => {
315-
ownable.assertOnlyOwner();
273+
ownable.as(OWNER).assertOnlyOwner();
316274
}).toThrow('ZOwnablePK: caller is not the owner');
317275
});
318276

319277
it('should fail when renouncing from unauthorized', () => {
320-
ownable.callerCtx.setCaller(UNAUTHORIZED);
321278
expect(() => {
322-
ownable.renounceOwnership();
323-
}).toThrow('ZOwnablePK: caller is not the owner');
279+
ownable.as(UNAUTHORIZED).renounceOwnership();
280+
});
324281
});
325282

326283
it('should fail when renouncing from authorized with bad nonce', () => {
327-
ownable.callerCtx.setCaller(OWNER);
328284
ownable.privateState.injectSecretNonce(BAD_NONCE);
329285
expect(() => {
330-
ownable.renounceOwnership();
331-
}).toThrow('ZOwnablePK: caller is not the owner');
286+
ownable.as(OWNER).renounceOwnership();
287+
});
332288
});
333289

334290
it('should fail when renouncing from unauthorized with bad nonce', () => {
335-
ownable.callerCtx.setCaller(UNAUTHORIZED);
336291
ownable.privateState.injectSecretNonce(BAD_NONCE);
337292
expect(() => {
338-
ownable.renounceOwnership();
339-
}).toThrow('ZOwnablePK: caller is not the owner');
293+
ownable.as(UNAUTHORIZED).renounceOwnership();
294+
});
340295
});
341296
});
342297

@@ -347,8 +302,7 @@ describe('ZOwnablePK', () => {
347302
secretNonce,
348303
);
349304

350-
ownable.callerCtx.setCaller(OWNER);
351-
expect(ownable.assertOnlyOwner()).to.not.throw;
305+
expect(ownable.as(OWNER).assertOnlyOwner()).to.not.throw;
352306
});
353307

354308
it('should fail when the authorized caller has the wrong nonce', () => {
@@ -361,9 +315,8 @@ describe('ZOwnablePK', () => {
361315
);
362316

363317
// Set caller and call circuit
364-
ownable.callerCtx.setCaller(OWNER);
365318
expect(() => {
366-
ownable.assertOnlyOwner();
319+
ownable.as(OWNER).assertOnlyOwner();
367320
}).toThrow('ZOwnablePK: caller is not the owner');
368321
});
369322

@@ -373,9 +326,8 @@ describe('ZOwnablePK', () => {
373326
secretNonce,
374327
);
375328

376-
ownable.callerCtx.setCaller(UNAUTHORIZED);
377329
expect(() => {
378-
ownable.assertOnlyOwner();
330+
ownable.as(UNAUTHORIZED).assertOnlyOwner();
379331
}).toThrow('ZOwnablePK: caller is not the owner');
380332
});
381333

@@ -389,9 +341,8 @@ describe('ZOwnablePK', () => {
389341
);
390342

391343
// Set unauthorized caller and call circuit
392-
ownable.callerCtx.setCaller(UNAUTHORIZED);
393344
expect(() => {
394-
ownable.assertOnlyOwner();
345+
ownable.as(UNAUTHORIZED).assertOnlyOwner();
395346
}).toThrow('ZOwnablePK: caller is not the owner');
396347
});
397348
});
@@ -522,12 +473,9 @@ describe('ZOwnablePK', () => {
522473
});
523474

524475
it('should allow anyone to transfer', () => {
525-
ownable.callerCtx.setCaller(OWNER);
526476
const id = createIdHash(Z_OWNER, secretNonce);
527-
expect(ownable._transferOwnership(id)).not.to.throw;
528-
529-
ownable.callerCtx.setCaller(UNAUTHORIZED);
530-
expect(ownable._transferOwnership(id)).not.to.throw;
477+
expect(ownable.as(OWNER)._transferOwnership(id)).not.to.throw;
478+
expect(ownable.as(UNAUTHORIZED)._transferOwnership(id)).not.to.throw;
531479
});
532480
});
533481
});

0 commit comments

Comments
 (0)