@openzeppelin/compact-contracts 0.1.0 → 0.3.0-alpha
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 +15 -16
- package/access/AccessControl.compact +3 -35
- package/access/Ownable.compact +47 -60
- package/access/ShieldedAccessControl.compact +43 -10
- package/access/ZOwnablePK.compact +45 -10
- package/crypto/ElGamal.compact +473 -0
- package/multisig/ForwarderPrivate.compact +229 -0
- package/multisig/ForwarderShielded.compact +149 -0
- package/multisig/ForwarderUnshielded.compact +152 -0
- package/multisig/ProposalManager.compact +328 -0
- package/multisig/ShieldedTreasury.compact +201 -0
- package/multisig/ShieldedTreasuryStateless.compact +76 -0
- package/multisig/Signer.compact +312 -0
- package/multisig/SignerManager.compact +205 -0
- package/multisig/UnshieldedTreasury.compact +114 -0
- package/multisig/presets/ShieldedMultiSig.compact +236 -0
- package/multisig/presets/ShieldedMultiSigV2.compact +280 -0
- package/multisig/presets/ShieldedMultiSigV3.compact +368 -0
- package/multisig/presets/forwarder/ForwarderPrivate.compact +125 -0
- package/multisig/presets/forwarder/ForwarderShielded.compact +62 -0
- package/multisig/presets/forwarder/ForwarderUnshielded.compact +64 -0
- package/package.json +12 -6
- package/security/Allowlist.compact +101 -0
- package/security/Blocklist.compact +99 -0
- package/security/Initializable.compact +18 -2
- package/security/Pausable.compact +2 -2
- package/token/FungibleToken.compact +79 -103
- package/token/MultiToken.compact +67 -93
- package/token/NativeShieldedToken.compact +285 -0
- package/token/NativeShieldedTokenCore.compact +343 -0
- package/token/NativeShieldedTokenFamily.compact +287 -0
- package/token/NonFungibleToken.compact +85 -110
- package/utils/Utils.compact +86 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.3.0-alpha (token/NonFungibleToken.compact)
|
|
3
3
|
|
|
4
|
-
pragma language_version >= 0.
|
|
4
|
+
pragma language_version >= 0.23.0;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @module NonFungibleToken
|
|
@@ -83,13 +83,19 @@ pragma language_version >= 0.21.0;
|
|
|
83
83
|
|
|
84
84
|
module NonFungibleToken {
|
|
85
85
|
import CompactStandardLibrary;
|
|
86
|
-
import "../security/Initializable" prefix Initializable_;
|
|
87
86
|
import "../utils/Utils" prefix Utils_;
|
|
88
87
|
|
|
89
88
|
/// Public state
|
|
90
89
|
export sealed ledger _name: Opaque<"string">;
|
|
91
90
|
export sealed ledger _symbol: Opaque<"string">;
|
|
92
91
|
|
|
92
|
+
/**
|
|
93
|
+
* @description Initialization flag, tracked per-module to avoid the compiler's
|
|
94
|
+
* shared transitive-dependency state bug (LFDT-Minokawa/compact#270). See the
|
|
95
|
+
* Initializable module for rationale.
|
|
96
|
+
*/
|
|
97
|
+
export ledger _isInitialized: Boolean;
|
|
98
|
+
|
|
93
99
|
/**
|
|
94
100
|
* @description Mapping from token IDs to their owner addresses.
|
|
95
101
|
* @type {Uint<128>} tokenId - The unique identifier for a token.
|
|
@@ -148,18 +154,6 @@ module NonFungibleToken {
|
|
|
148
154
|
*/
|
|
149
155
|
witness wit_NonFungibleTokenSK(): Bytes<32>;
|
|
150
156
|
|
|
151
|
-
/**
|
|
152
|
-
* @description Returns a canonical zero Either value (left variant with zero Bytes<32>).
|
|
153
|
-
* Used as the zero value for mint/burn operations and cleared approvals.
|
|
154
|
-
*
|
|
155
|
-
* @return {Either<Bytes<32>, ContractAddress>} - The zero value.
|
|
156
|
-
*/
|
|
157
|
-
export pure circuit ZERO(): Either<Bytes<32>, ContractAddress> {
|
|
158
|
-
return Either<Bytes<32>, ContractAddress> {
|
|
159
|
-
is_left: true, left: default<Bytes<32>>, right: default<ContractAddress>
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
157
|
/**
|
|
164
158
|
* @description Initializes the contract by setting the name and symbol.
|
|
165
159
|
*
|
|
@@ -177,11 +171,38 @@ module NonFungibleToken {
|
|
|
177
171
|
* @return {[]} - Empty tuple.
|
|
178
172
|
*/
|
|
179
173
|
export circuit initialize(name_: Opaque<"string">, symbol_: Opaque<"string">): [] {
|
|
180
|
-
|
|
174
|
+
assertNotInitialized();
|
|
175
|
+
_isInitialized = true;
|
|
181
176
|
_name = disclose(name_);
|
|
182
177
|
_symbol = disclose(symbol_);
|
|
183
178
|
}
|
|
184
179
|
|
|
180
|
+
/**
|
|
181
|
+
* @description Asserts that the contract has been initialized, throwing an error if not.
|
|
182
|
+
*
|
|
183
|
+
* Requirements:
|
|
184
|
+
*
|
|
185
|
+
* - Contract must be initialized.
|
|
186
|
+
*
|
|
187
|
+
* @return {[]} - Empty tuple.
|
|
188
|
+
*/
|
|
189
|
+
circuit assertInitialized(): [] {
|
|
190
|
+
assert(_isInitialized, "NonFungibleToken: contract not initialized");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @description Asserts that the contract has not been initialized, throwing an error if it has.
|
|
195
|
+
*
|
|
196
|
+
* Requirements:
|
|
197
|
+
*
|
|
198
|
+
* - Contract must not be initialized.
|
|
199
|
+
*
|
|
200
|
+
* @return {[]} - Empty tuple.
|
|
201
|
+
*/
|
|
202
|
+
circuit assertNotInitialized(): [] {
|
|
203
|
+
assert(!_isInitialized, "NonFungibleToken: contract already initialized");
|
|
204
|
+
}
|
|
205
|
+
|
|
185
206
|
/**
|
|
186
207
|
* @description Returns the number of tokens in `owner`'s account.
|
|
187
208
|
*
|
|
@@ -195,7 +216,7 @@ module NonFungibleToken {
|
|
|
195
216
|
* @return {Uint<128>} - The number of tokens in `owner`'s account.
|
|
196
217
|
*/
|
|
197
218
|
export circuit balanceOf(owner: Either<Bytes<32>, ContractAddress>): Uint<128> {
|
|
198
|
-
|
|
219
|
+
assertInitialized();
|
|
199
220
|
const canonOwner = Utils_canonicalize<Bytes<32>, ContractAddress>(owner);
|
|
200
221
|
|
|
201
222
|
if (!_balances.member(disclose(canonOwner))) {
|
|
@@ -219,7 +240,7 @@ module NonFungibleToken {
|
|
|
219
240
|
* @return {Either<Bytes<32>, ContractAddress>} - The account that owns the token.
|
|
220
241
|
*/
|
|
221
242
|
export circuit ownerOf(tokenId: Uint<128>): Either<Bytes<32>, ContractAddress> {
|
|
222
|
-
|
|
243
|
+
assertInitialized();
|
|
223
244
|
return _requireOwned(tokenId);
|
|
224
245
|
}
|
|
225
246
|
|
|
@@ -235,7 +256,7 @@ module NonFungibleToken {
|
|
|
235
256
|
* @return {Opaque<"string">} - The token name.
|
|
236
257
|
*/
|
|
237
258
|
export circuit name(): Opaque<"string"> {
|
|
238
|
-
|
|
259
|
+
assertInitialized();
|
|
239
260
|
return _name;
|
|
240
261
|
}
|
|
241
262
|
|
|
@@ -251,7 +272,7 @@ module NonFungibleToken {
|
|
|
251
272
|
* @return {Opaque<"string">} - The token symbol.
|
|
252
273
|
*/
|
|
253
274
|
export circuit symbol(): Opaque<"string"> {
|
|
254
|
-
|
|
275
|
+
assertInitialized();
|
|
255
276
|
return _symbol;
|
|
256
277
|
}
|
|
257
278
|
|
|
@@ -275,7 +296,7 @@ module NonFungibleToken {
|
|
|
275
296
|
* @return {Opaque<"string">} - the token id's URI.
|
|
276
297
|
*/
|
|
277
298
|
export circuit tokenURI(tokenId: Uint<128>): Opaque<"string"> {
|
|
278
|
-
|
|
299
|
+
assertInitialized();
|
|
279
300
|
_requireOwned(tokenId);
|
|
280
301
|
|
|
281
302
|
if (!_tokenURIs.member(disclose(tokenId))) {
|
|
@@ -302,7 +323,7 @@ module NonFungibleToken {
|
|
|
302
323
|
* @return {[]} - Empty tuple.
|
|
303
324
|
*/
|
|
304
325
|
export circuit _setTokenURI(tokenId: Uint<128>, tokenURI: Opaque<"string">): [] {
|
|
305
|
-
|
|
326
|
+
assertInitialized();
|
|
306
327
|
_requireOwned(tokenId);
|
|
307
328
|
|
|
308
329
|
return _tokenURIs.insert(disclose(tokenId), disclose(tokenURI));
|
|
@@ -330,7 +351,7 @@ module NonFungibleToken {
|
|
|
330
351
|
* @return {[]} - Empty tuple.
|
|
331
352
|
*/
|
|
332
353
|
export circuit approve(to: Either<Bytes<32>, ContractAddress>, tokenId: Uint<128>): [] {
|
|
333
|
-
|
|
354
|
+
assertInitialized();
|
|
334
355
|
const auth = left<Bytes<32>, ContractAddress>(_computeAccountId());
|
|
335
356
|
_approve(to, tokenId, auth);
|
|
336
357
|
}
|
|
@@ -349,7 +370,7 @@ module NonFungibleToken {
|
|
|
349
370
|
* @return {Either<Bytes<32>, ContractAddress>} - The account approved to manage the token
|
|
350
371
|
*/
|
|
351
372
|
export circuit getApproved(tokenId: Uint<128>): Either<Bytes<32>, ContractAddress> {
|
|
352
|
-
|
|
373
|
+
assertInitialized();
|
|
353
374
|
_requireOwned(tokenId);
|
|
354
375
|
|
|
355
376
|
return _getApproved(tokenId);
|
|
@@ -377,7 +398,7 @@ module NonFungibleToken {
|
|
|
377
398
|
operator: Either<Bytes<32>, ContractAddress>,
|
|
378
399
|
approved: Boolean
|
|
379
400
|
): [] {
|
|
380
|
-
|
|
401
|
+
assertInitialized();
|
|
381
402
|
const owner = left<Bytes<32>, ContractAddress>(_computeAccountId());
|
|
382
403
|
_setApprovalForAll(owner, operator, approved);
|
|
383
404
|
}
|
|
@@ -399,7 +420,7 @@ module NonFungibleToken {
|
|
|
399
420
|
owner: Either<Bytes<32>, ContractAddress>,
|
|
400
421
|
operator: Either<Bytes<32>, ContractAddress>
|
|
401
422
|
): Boolean {
|
|
402
|
-
|
|
423
|
+
assertInitialized();
|
|
403
424
|
const canonOwner = Utils_canonicalize<Bytes<32>, ContractAddress>(owner);
|
|
404
425
|
const canonOp = Utils_canonicalize<Bytes<32>, ContractAddress>(operator);
|
|
405
426
|
|
|
@@ -439,7 +460,7 @@ module NonFungibleToken {
|
|
|
439
460
|
to: Either<Bytes<32>, ContractAddress>,
|
|
440
461
|
tokenId: Uint<128>
|
|
441
462
|
): [] {
|
|
442
|
-
|
|
463
|
+
assertInitialized();
|
|
443
464
|
const isContractAddr = !to.is_left;
|
|
444
465
|
assert(!isContractAddr, "NonFungibleToken: unsafe transfer");
|
|
445
466
|
|
|
@@ -476,8 +497,8 @@ module NonFungibleToken {
|
|
|
476
497
|
to: Either<Bytes<32>, ContractAddress>,
|
|
477
498
|
tokenId: Uint<128>
|
|
478
499
|
): [] {
|
|
479
|
-
|
|
480
|
-
assert(!
|
|
500
|
+
assertInitialized();
|
|
501
|
+
assert(!Utils_isTargetZero(to), "NonFungibleToken: invalid receiver");
|
|
481
502
|
// Setting an "auth" argument enables the `_isAuthorized` check which verifies that the token exists
|
|
482
503
|
// (fromAddress != 0). Therefore, it is not needed to verify that the return value is not 0 here.
|
|
483
504
|
const auth = left<Bytes<32>, ContractAddress>(_computeAccountId());
|
|
@@ -500,9 +521,9 @@ module NonFungibleToken {
|
|
|
500
521
|
* @return {Either<Bytes<32>, ContractAddress>} - The owner of the token
|
|
501
522
|
*/
|
|
502
523
|
export circuit _ownerOf(tokenId: Uint<128>): Either<Bytes<32>, ContractAddress> {
|
|
503
|
-
|
|
524
|
+
assertInitialized();
|
|
504
525
|
if (!_owners.member(disclose(tokenId))) {
|
|
505
|
-
return
|
|
526
|
+
return Utils_zeroAccount();
|
|
506
527
|
}
|
|
507
528
|
|
|
508
529
|
return _owners.lookup(disclose(tokenId));
|
|
@@ -521,9 +542,9 @@ module NonFungibleToken {
|
|
|
521
542
|
* @return {Either<Bytes<32>, ContractAddress>} - An account approved to spend `tokenId`
|
|
522
543
|
*/
|
|
523
544
|
export circuit _getApproved(tokenId: Uint<128>): Either<Bytes<32>, ContractAddress> {
|
|
524
|
-
|
|
545
|
+
assertInitialized();
|
|
525
546
|
if (!_tokenApprovals.member(disclose(tokenId))) {
|
|
526
|
-
return
|
|
547
|
+
return Utils_zeroAccount();
|
|
527
548
|
}
|
|
528
549
|
return _tokenApprovals.lookup(disclose(tokenId));
|
|
529
550
|
}
|
|
@@ -551,11 +572,11 @@ module NonFungibleToken {
|
|
|
551
572
|
spender: Either<Bytes<32>, ContractAddress>,
|
|
552
573
|
tokenId: Uint<128>
|
|
553
574
|
): Boolean {
|
|
554
|
-
|
|
575
|
+
assertInitialized();
|
|
555
576
|
const canonOwner = Utils_canonicalize<Bytes<32>, ContractAddress>(owner);
|
|
556
577
|
const canonSpender = Utils_canonicalize<Bytes<32>, ContractAddress>(spender);
|
|
557
578
|
|
|
558
|
-
return (!
|
|
579
|
+
return (!Utils_isTargetZero(disclose(canonSpender)) &&
|
|
559
580
|
(disclose(canonOwner) == disclose(canonSpender) ||
|
|
560
581
|
isApprovedForAll(canonOwner, canonSpender) ||
|
|
561
582
|
_getApproved(tokenId) == disclose(canonSpender)));
|
|
@@ -584,9 +605,9 @@ module NonFungibleToken {
|
|
|
584
605
|
spender: Either<Bytes<32>, ContractAddress>,
|
|
585
606
|
tokenId: Uint<128>
|
|
586
607
|
): [] {
|
|
587
|
-
|
|
608
|
+
assertInitialized();
|
|
588
609
|
if (!_isAuthorized(owner, spender, tokenId)) {
|
|
589
|
-
assert(!
|
|
610
|
+
assert(!Utils_isTargetZero(owner), "NonFungibleToken: nonexistent token");
|
|
590
611
|
assert(false, "NonFungibleToken: insufficient approval");
|
|
591
612
|
}
|
|
592
613
|
}
|
|
@@ -610,26 +631,26 @@ module NonFungibleToken {
|
|
|
610
631
|
tokenId: Uint<128>,
|
|
611
632
|
auth: Either<Bytes<32>, ContractAddress>
|
|
612
633
|
): Either<Bytes<32>, ContractAddress> {
|
|
613
|
-
|
|
634
|
+
assertInitialized();
|
|
614
635
|
const canonTo = Utils_canonicalize<Bytes<32>, ContractAddress>(to);
|
|
615
636
|
const canonAuth = Utils_canonicalize<Bytes<32>, ContractAddress>(auth);
|
|
616
637
|
const fromAddress = _ownerOf(tokenId);
|
|
617
638
|
|
|
618
639
|
// Perform (optional) operator check
|
|
619
|
-
if (!
|
|
640
|
+
if (!Utils_isTargetZero(disclose(canonAuth))) {
|
|
620
641
|
_checkAuthorized(fromAddress, canonAuth, tokenId);
|
|
621
642
|
}
|
|
622
643
|
|
|
623
644
|
// Execute the update
|
|
624
|
-
if (!
|
|
645
|
+
if (!Utils_isTargetZero(disclose(fromAddress))) {
|
|
625
646
|
// Clear approval. No need to re-authorize
|
|
626
|
-
_approve(
|
|
647
|
+
_approve(Utils_zeroAccount(), tokenId, Utils_zeroAccount());
|
|
627
648
|
const canonFrom = Utils_canonicalize<Bytes<32>, ContractAddress>(fromAddress);
|
|
628
649
|
const newBalance = _balances.lookup(disclose(canonFrom)) - 1 as Uint<128>;
|
|
629
650
|
_balances.insert(disclose(canonFrom), disclose(newBalance));
|
|
630
651
|
}
|
|
631
652
|
|
|
632
|
-
if (!
|
|
653
|
+
if (!Utils_isTargetZero(disclose(canonTo))) {
|
|
633
654
|
if (!_balances.member(disclose(canonTo))) {
|
|
634
655
|
_balances.insert(disclose(canonTo), 0);
|
|
635
656
|
}
|
|
@@ -659,7 +680,7 @@ module NonFungibleToken {
|
|
|
659
680
|
* @return {[]} - Empty tuple.
|
|
660
681
|
*/
|
|
661
682
|
export circuit _mint(to: Either<Bytes<32>, ContractAddress>, tokenId: Uint<128>): [] {
|
|
662
|
-
|
|
683
|
+
assertInitialized();
|
|
663
684
|
const isContractAddr = !to.is_left;
|
|
664
685
|
assert(!isContractAddr, "NonFungibleToken: unsafe transfer");
|
|
665
686
|
|
|
@@ -689,12 +710,12 @@ module NonFungibleToken {
|
|
|
689
710
|
to: Either<Bytes<32>, ContractAddress>,
|
|
690
711
|
tokenId: Uint<128>
|
|
691
712
|
): [] {
|
|
692
|
-
|
|
693
|
-
assert(!
|
|
713
|
+
assertInitialized();
|
|
714
|
+
assert(!Utils_isTargetZero(to), "NonFungibleToken: invalid receiver");
|
|
694
715
|
|
|
695
|
-
const previousOwner = _update(to, tokenId,
|
|
716
|
+
const previousOwner = _update(to, tokenId, Utils_zeroAccount());
|
|
696
717
|
|
|
697
|
-
assert(
|
|
718
|
+
assert(Utils_isTargetZero(previousOwner), "NonFungibleToken: invalid sender");
|
|
698
719
|
}
|
|
699
720
|
|
|
700
721
|
/**
|
|
@@ -713,9 +734,9 @@ module NonFungibleToken {
|
|
|
713
734
|
* @return {[]} - Empty tuple.
|
|
714
735
|
*/
|
|
715
736
|
export circuit _burn(tokenId: Uint<128>): [] {
|
|
716
|
-
|
|
717
|
-
const previousOwner = _update(
|
|
718
|
-
assert(!
|
|
737
|
+
assertInitialized();
|
|
738
|
+
const previousOwner = _update(Utils_zeroAccount(), tokenId, Utils_zeroAccount());
|
|
739
|
+
assert(!Utils_isTargetZero(previousOwner), "NonFungibleToken: invalid sender");
|
|
719
740
|
_tokenURIs.remove(disclose(tokenId));
|
|
720
741
|
}
|
|
721
742
|
|
|
@@ -746,7 +767,7 @@ module NonFungibleToken {
|
|
|
746
767
|
to: Either<Bytes<32>, ContractAddress>,
|
|
747
768
|
tokenId: Uint<128>
|
|
748
769
|
): [] {
|
|
749
|
-
|
|
770
|
+
assertInitialized();
|
|
750
771
|
const isContractAddr = !to.is_left;
|
|
751
772
|
assert(!isContractAddr, "NonFungibleToken: unsafe transfer");
|
|
752
773
|
|
|
@@ -780,12 +801,12 @@ module NonFungibleToken {
|
|
|
780
801
|
to: Either<Bytes<32>, ContractAddress>,
|
|
781
802
|
tokenId: Uint<128>
|
|
782
803
|
): [] {
|
|
783
|
-
|
|
784
|
-
assert(!
|
|
804
|
+
assertInitialized();
|
|
805
|
+
assert(!Utils_isTargetZero(to), "NonFungibleToken: invalid receiver");
|
|
785
806
|
|
|
786
|
-
const previousOwner = _update(to, tokenId,
|
|
807
|
+
const previousOwner = _update(to, tokenId, Utils_zeroAccount());
|
|
787
808
|
|
|
788
|
-
assert(!
|
|
809
|
+
assert(!Utils_isTargetZero(previousOwner), "NonFungibleToken: nonexistent token");
|
|
789
810
|
|
|
790
811
|
const canonFrom = Utils_canonicalize<Bytes<32>, ContractAddress>(fromAddress);
|
|
791
812
|
assert(previousOwner == canonFrom, "NonFungibleToken: incorrect owner");
|
|
@@ -812,15 +833,15 @@ module NonFungibleToken {
|
|
|
812
833
|
tokenId: Uint<128>,
|
|
813
834
|
auth: Either<Bytes<32>, ContractAddress>
|
|
814
835
|
): [] {
|
|
815
|
-
|
|
836
|
+
assertInitialized();
|
|
816
837
|
// Canonicalize + normalize `to`
|
|
817
838
|
const canonTo = Utils_canonicalize<Bytes<32>, ContractAddress>(to);
|
|
818
|
-
const normalizedTo =
|
|
839
|
+
const normalizedTo = Utils_isTargetZero(canonTo) ? Utils_zeroAccount() : canonTo;
|
|
819
840
|
|
|
820
841
|
// Canonicalize auth
|
|
821
842
|
const canonAuth = Utils_canonicalize<Bytes<32>, ContractAddress>(auth);
|
|
822
843
|
|
|
823
|
-
if (!
|
|
844
|
+
if (!Utils_isTargetZero(disclose(canonAuth))) {
|
|
824
845
|
const owner = _requireOwned(tokenId);
|
|
825
846
|
|
|
826
847
|
// We do not use _isAuthorized because single-token approvals should not be able to call approve
|
|
@@ -853,12 +874,12 @@ module NonFungibleToken {
|
|
|
853
874
|
operator: Either<Bytes<32>, ContractAddress>,
|
|
854
875
|
approved: Boolean
|
|
855
876
|
): [] {
|
|
856
|
-
|
|
877
|
+
assertInitialized();
|
|
857
878
|
const canonOwner = Utils_canonicalize<Bytes<32>, ContractAddress>(owner);
|
|
858
|
-
assert(!
|
|
879
|
+
assert(!Utils_isTargetZero(canonOwner), "NonFungibleToken: invalid owner");
|
|
859
880
|
|
|
860
881
|
const canonOp = Utils_canonicalize<Bytes<32>, ContractAddress>(operator);
|
|
861
|
-
assert(!
|
|
882
|
+
assert(!Utils_isTargetZero(canonOp), "NonFungibleToken: invalid operator");
|
|
862
883
|
|
|
863
884
|
if (!_operatorApprovals.member(disclose(canonOwner))) {
|
|
864
885
|
_operatorApprovals.insert(
|
|
@@ -885,10 +906,10 @@ module NonFungibleToken {
|
|
|
885
906
|
* @return {Either<Bytes<32>, ContractAddress>} - The owner of `tokenId`
|
|
886
907
|
*/
|
|
887
908
|
export circuit _requireOwned(tokenId: Uint<128>): Either<Bytes<32>, ContractAddress> {
|
|
888
|
-
|
|
909
|
+
assertInitialized();
|
|
889
910
|
const owner = _ownerOf(tokenId);
|
|
890
911
|
|
|
891
|
-
assert(!
|
|
912
|
+
assert(!Utils_isTargetZero(owner), "NonFungibleToken: nonexistent token");
|
|
892
913
|
return owner;
|
|
893
914
|
}
|
|
894
915
|
|
|
@@ -903,52 +924,6 @@ module NonFungibleToken {
|
|
|
903
924
|
* @returns {Bytes<32>} accountId - The computed account identifier.
|
|
904
925
|
*/
|
|
905
926
|
circuit _computeAccountId(): Bytes<32> {
|
|
906
|
-
return
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
/**
|
|
910
|
-
* @description Computes an account identifier without on-chain state, allowing a user to derive
|
|
911
|
-
* their identity commitment before submitting it in a token operation.
|
|
912
|
-
* This is the off-chain counterpart to {_computeAccountId} and produces an identical result
|
|
913
|
-
* given the same inputs.
|
|
914
|
-
*
|
|
915
|
-
* @warning OpSec: The `secretKey` parameter is a sensitive secret. Mishandling it can
|
|
916
|
-
* permanently compromise the security of this system:
|
|
917
|
-
*
|
|
918
|
-
* - **Never log or persist** the `secretKey` in plaintext — avoid browser devtools,
|
|
919
|
-
* application logs, analytics pipelines, or any observable side-channel.
|
|
920
|
-
* - **Store offline or in secure enclaves** — hardware security modules (HSMs),
|
|
921
|
-
* air-gapped devices, or encrypted vaults are strongly preferred over hot storage.
|
|
922
|
-
* - **Use cryptographically secure randomness** — generate keys with `crypto.getRandomValues()`
|
|
923
|
-
* or equivalent; weak or predictable keys can be brute-forced to reveal your identity.
|
|
924
|
-
* - **Treat key loss as identity loss** — a lost key cannot be recovered.
|
|
925
|
-
* - **Avoid calling this circuit in untrusted environments** — executing this in an
|
|
926
|
-
* unverified browser extension, compromised runtime, or shared machine may expose
|
|
927
|
-
* the key to a malicious observer.
|
|
928
|
-
*
|
|
929
|
-
* ## ID Derivation
|
|
930
|
-
* `accountId = persistentHash(secretKey)`
|
|
931
|
-
*
|
|
932
|
-
* @param {Bytes<32>} secretKey - A 32-byte cryptographically secure random value.
|
|
933
|
-
*
|
|
934
|
-
* @returns {Bytes<32>} accountId - The computed account identifier.
|
|
935
|
-
*/
|
|
936
|
-
export pure circuit computeAccountId(secretKey: Bytes<32>): Bytes<32> {
|
|
937
|
-
return persistentHash<Vector<1, Bytes<32>>>([secretKey]);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
/**
|
|
941
|
-
* @description Returns `true` if `target`'s active branch (as indicated by `is_left`)
|
|
942
|
-
* holds the zero value.
|
|
943
|
-
*
|
|
944
|
-
* @param {Either<Bytes<32>, ContractAddress>} target - The value to check.
|
|
945
|
-
* @returns {Boolean} - `true` if the active branch is zero, `false` otherwise.
|
|
946
|
-
*/
|
|
947
|
-
circuit _isTargetZero(target: Either<Bytes<32>, ContractAddress>): Boolean {
|
|
948
|
-
if (target.is_left) {
|
|
949
|
-
return target.left == default<Bytes<32>>;
|
|
950
|
-
} else {
|
|
951
|
-
return target.right == default<ContractAddress>;
|
|
952
|
-
}
|
|
927
|
+
return Utils_computeAccountId(wit_NonFungibleTokenSK());
|
|
953
928
|
}
|
|
954
929
|
}
|
package/utils/Utils.compact
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.3.0-alpha (utils/Utils.compact)
|
|
3
3
|
|
|
4
|
-
pragma language_version >= 0.
|
|
4
|
+
pragma language_version >= 0.23.0;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @module Utils.
|
|
@@ -95,4 +95,88 @@ module Utils {
|
|
|
95
95
|
? Either<T1, T2>{ is_left: true, left: value.left, right: default<T2> }
|
|
96
96
|
: Either<T1, T2>{ is_left: false, left: default<T1>, right: value.right };
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @description Returns the canonical zero `Either<Bytes<32>, ContractAddress>` value: the
|
|
101
|
+
* left variant (`Bytes<32>`) set to zero. Used as the sentinel for mint/burn operations
|
|
102
|
+
* (a zero `from` signals a mint, a zero `to` signals a burn) and for cleared approvals.
|
|
103
|
+
*
|
|
104
|
+
* The left variant is chosen so that `isTargetZero` checks against `default<Bytes<32>>`,
|
|
105
|
+
* and to avoid triggering contract-address guards (e.g. circuits that check `!to.is_left`
|
|
106
|
+
* before delegating to an `_unsafe` variant). A right variant with `default<ContractAddress>`
|
|
107
|
+
* would also pass `isTargetZero`, but the left variant keeps guards and error messages consistent.
|
|
108
|
+
*
|
|
109
|
+
* @return {Either<Bytes<32>, ContractAddress>} - The canonical zero value.
|
|
110
|
+
*/
|
|
111
|
+
export pure circuit zeroAccount(): Either<Bytes<32>, ContractAddress> {
|
|
112
|
+
return Either<Bytes<32>, ContractAddress> {
|
|
113
|
+
is_left: true, left: default<Bytes<32>>, right: default<ContractAddress>
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @description Returns `true` if `target`'s active branch (as indicated by `is_left`)
|
|
119
|
+
* holds the zero value.
|
|
120
|
+
*
|
|
121
|
+
* @param {Either<Bytes<32>, ContractAddress>} target - The value to check.
|
|
122
|
+
* @return {Boolean} - `true` if the active branch is zero, `false` otherwise.
|
|
123
|
+
*/
|
|
124
|
+
export pure circuit isTargetZero(target: Either<Bytes<32>, ContractAddress>): Boolean {
|
|
125
|
+
if (target.is_left) {
|
|
126
|
+
return target.left == default<Bytes<32>>;
|
|
127
|
+
} else {
|
|
128
|
+
return target.right == default<ContractAddress>;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @description Computes an account identifier without on-chain state, allowing a user to derive
|
|
134
|
+
* their identity commitment before submitting an operation.
|
|
135
|
+
*
|
|
136
|
+
* @warning OpSec: The `secretKey` parameter is a sensitive secret. Mishandling it can
|
|
137
|
+
* permanently compromise the security of this system:
|
|
138
|
+
*
|
|
139
|
+
* - **Never log or persist** the `secretKey` in plaintext — avoid browser devtools,
|
|
140
|
+
* application logs, analytics pipelines, or any observable side-channel.
|
|
141
|
+
* - **Store offline or in secure enclaves** — hardware security modules (HSMs),
|
|
142
|
+
* air-gapped devices, or encrypted vaults are strongly preferred over hot storage.
|
|
143
|
+
* - **Use cryptographically secure randomness** — generate keys with `crypto.getRandomValues()`
|
|
144
|
+
* or equivalent; weak or predictable keys can be brute-forced to reveal your identity.
|
|
145
|
+
* - **Treat key loss as identity loss** — a lost key cannot be recovered.
|
|
146
|
+
* - **Avoid calling this circuit in untrusted environments** — executing this in an
|
|
147
|
+
* unverified browser extension, compromised runtime, or shared machine may expose
|
|
148
|
+
* the key to a malicious observer.
|
|
149
|
+
*
|
|
150
|
+
* ## ID Derivation
|
|
151
|
+
* `accountId = persistentHash(secretKey)`
|
|
152
|
+
*
|
|
153
|
+
* @param {Bytes<32>} secretKey - A 32-byte cryptographically secure random value.
|
|
154
|
+
*
|
|
155
|
+
* @returns {Bytes<32>} accountId - The computed account identifier.
|
|
156
|
+
*/
|
|
157
|
+
export pure circuit computeAccountId(secretKey: Bytes<32>): Bytes<32> {
|
|
158
|
+
return persistentHash<Vector<1, Bytes<32>>>([secretKey]);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @description Returns the current contract's address as an
|
|
163
|
+
* `Either<ZswapCoinPublicKey, ContractAddress>` for use as a
|
|
164
|
+
* recipient in shielded send operations (deposits and receiving change).
|
|
165
|
+
*
|
|
166
|
+
* @returns {Either<ZswapCoinPublicKey, ContractAddress>} The contract's address as a recipient.
|
|
167
|
+
*/
|
|
168
|
+
export circuit selfAsRecipient(): Either<ZswapCoinPublicKey, ContractAddress> {
|
|
169
|
+
return right<ZswapCoinPublicKey, ContractAddress>(kernel.self());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @description The maximum value representable by a `Uint<128>`.
|
|
174
|
+
*
|
|
175
|
+
* @notice TODO: Remove once a math module providing this constant is available.
|
|
176
|
+
*
|
|
177
|
+
* @returns {Uint<128>} `2^128 - 1`.
|
|
178
|
+
*/
|
|
179
|
+
export pure circuit UINT128_MAX(): Uint<128> {
|
|
180
|
+
return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
|
|
181
|
+
}
|
|
98
182
|
}
|