@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.1

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.
Files changed (164) hide show
  1. package/README.md +76 -162
  2. package/config/eip170.ts +30 -0
  3. package/contracts/factory.sol +30 -34
  4. package/contracts/factory_upgradeable.sol +11 -7
  5. package/contracts/lib/common/util.sol +40 -0
  6. package/contracts/lib/interfaces/ILockableCapability.sol +318 -0
  7. package/contracts/lib/interfaces/{izeto.sol → IZeto.sol} +13 -1
  8. package/contracts/lib/interfaces/{izeto_initializable.sol → IZetoInitializable.sol} +14 -12
  9. package/contracts/lib/interfaces/{izeto_kyc.sol → IZetoKyc.sol} +3 -3
  10. package/contracts/lib/interfaces/IZetoLockHooks.sol +42 -0
  11. package/contracts/lib/interfaces/IZetoLockableCapability.sol +237 -0
  12. package/contracts/lib/interfaces/IZetoStorage.sol +106 -0
  13. package/contracts/lib/interfaces/{izeto_lockable.sol → IZetoVerifier.sol} +8 -21
  14. package/contracts/lib/registry.sol +74 -26
  15. package/contracts/lib/storage/base.sol +210 -0
  16. package/contracts/lib/storage/nullifier.sol +166 -0
  17. package/contracts/lib/zeto_common.sol +277 -28
  18. package/contracts/lib/zeto_fungible.sol +443 -33
  19. package/contracts/lib/zeto_fungible_base.sol +69 -0
  20. package/contracts/lib/zeto_fungible_burn.sol +83 -53
  21. package/contracts/lib/zeto_fungible_burn_nullifier.sol +115 -72
  22. package/contracts/lib/zeto_fungible_nullifier.sol +167 -0
  23. package/contracts/lib/zeto_lockable.sol +219 -0
  24. package/contracts/lib/zeto_lockable_lib.sol +460 -0
  25. package/contracts/lib/zeto_lockable_storage.sol +43 -0
  26. package/contracts/lib/zeto_non_fungible.sol +228 -0
  27. package/contracts/lib/zeto_non_fungible_base.sol +61 -0
  28. package/contracts/lib/zeto_non_fungible_nullifier.sol +61 -0
  29. package/contracts/test/escrow1.sol +90 -34
  30. package/contracts/test/escrow2.sol +64 -29
  31. package/contracts/test/qurrency.sol +10 -2
  32. package/contracts/test/smt.sol +6 -1
  33. package/contracts/test/tendecimals.sol +14 -12
  34. package/contracts/verifiers/impl/anon.sol +189 -0
  35. package/contracts/verifiers/impl/anon_batch.sol +301 -0
  36. package/contracts/verifiers/impl/anon_enc.sol +266 -0
  37. package/contracts/verifiers/impl/anon_enc_batch.sol +602 -0
  38. package/contracts/verifiers/impl/anon_enc_nullifier.sol +287 -0
  39. package/contracts/verifiers/impl/anon_enc_nullifier_batch.sol +679 -0
  40. package/contracts/verifiers/impl/anon_enc_nullifier_kyc.sol +294 -0
  41. package/contracts/verifiers/impl/anon_enc_nullifier_kyc_batch.sol +686 -0
  42. package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation.sol +413 -0
  43. package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation_batch.sol +1141 -0
  44. package/contracts/verifiers/impl/anon_nullifier_kyc_transfer.sol +217 -0
  45. package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked.sol +196 -0
  46. package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked_batch.sol +308 -0
  47. package/contracts/verifiers/impl/anon_nullifier_kyc_transfer_batch.sol +385 -0
  48. package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer.sol +497 -0
  49. package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer_batch.sol +1001 -0
  50. package/contracts/verifiers/{verifier_anon_nullifier_transferLocked.sol → impl/anon_nullifier_transfer.sol} +12 -19
  51. package/contracts/verifiers/{verifier_anon_nullifier_transferLocked_batch.sol → impl/anon_nullifier_transfer_batch.sol} +44 -51
  52. package/contracts/verifiers/impl/burn.sol +182 -0
  53. package/contracts/verifiers/impl/burn_batch.sol +238 -0
  54. package/contracts/verifiers/impl/burn_nullifier.sol +203 -0
  55. package/contracts/verifiers/impl/burn_nullifier_batch.sol +315 -0
  56. package/contracts/verifiers/impl/deposit.sol +182 -0
  57. package/contracts/verifiers/impl/deposit_kyc.sol +189 -0
  58. package/contracts/verifiers/impl/nf_anon.sol +175 -0
  59. package/contracts/verifiers/{verifier_nf_anon_nullifier_transferLocked.sol → impl/nf_anon_nullifier_transfer.sol} +6 -13
  60. package/contracts/verifiers/impl/withdraw.sol +189 -0
  61. package/contracts/verifiers/impl/withdraw_batch.sol +245 -0
  62. package/contracts/verifiers/impl/withdraw_nullifier.sol +210 -0
  63. package/contracts/verifiers/impl/withdraw_nullifier_batch.sol +322 -0
  64. package/contracts/verifiers/verifier_anon.sol +31 -186
  65. package/contracts/verifiers/verifier_anon_batch.sol +31 -298
  66. package/contracts/verifiers/verifier_anon_enc.sol +31 -263
  67. package/contracts/verifiers/verifier_anon_enc_batch.sol +31 -599
  68. package/contracts/verifiers/verifier_anon_enc_nullifier.sol +31 -284
  69. package/contracts/verifiers/verifier_anon_enc_nullifier_batch.sol +33 -676
  70. package/contracts/verifiers/verifier_anon_enc_nullifier_kyc.sol +31 -291
  71. package/contracts/verifiers/verifier_anon_enc_nullifier_kyc_batch.sol +33 -683
  72. package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation.sol +33 -410
  73. package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation_batch.sol +33 -1138
  74. package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer.sol +33 -214
  75. package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked.sol +33 -221
  76. package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked_batch.sol +33 -389
  77. package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer_batch.sol +33 -382
  78. package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer.sol +33 -221
  79. package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer_batch.sol +33 -389
  80. package/contracts/verifiers/verifier_anon_nullifier_transfer.sol +33 -207
  81. package/contracts/verifiers/verifier_anon_nullifier_transfer_batch.sol +33 -375
  82. package/contracts/verifiers/verifier_burn.sol +31 -179
  83. package/contracts/verifiers/verifier_burn_batch.sol +31 -235
  84. package/contracts/verifiers/verifier_burn_nullifier.sol +31 -200
  85. package/contracts/verifiers/verifier_burn_nullifier_batch.sol +31 -312
  86. package/contracts/verifiers/verifier_deposit.sol +31 -179
  87. package/contracts/verifiers/verifier_deposit_kyc.sol +34 -0
  88. package/contracts/verifiers/verifier_nf_anon.sol +31 -172
  89. package/contracts/verifiers/verifier_nf_anon_nullifier_transfer.sol +33 -179
  90. package/contracts/verifiers/verifier_withdraw.sol +31 -186
  91. package/contracts/verifiers/verifier_withdraw_batch.sol +31 -242
  92. package/contracts/verifiers/verifier_withdraw_nullifier.sol +31 -207
  93. package/contracts/verifiers/verifier_withdraw_nullifier_batch.sol +33 -319
  94. package/contracts/zeto_anon.sol +77 -231
  95. package/contracts/zeto_anon_burnable.sol +56 -12
  96. package/contracts/zeto_anon_enc.sol +93 -190
  97. package/contracts/zeto_anon_enc_nullifier.sol +249 -195
  98. package/contracts/zeto_anon_enc_nullifier_kyc.sol +51 -232
  99. package/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +231 -238
  100. package/contracts/zeto_anon_nullifier.sol +164 -298
  101. package/contracts/zeto_anon_nullifier_burnable.sol +68 -18
  102. package/contracts/zeto_anon_nullifier_kyc.sol +40 -345
  103. package/contracts/zeto_anon_nullifier_qurrency.sol +217 -361
  104. package/contracts/zeto_nf_anon.sol +55 -130
  105. package/contracts/zeto_nf_anon_nullifier.sol +90 -152
  106. package/hardhat.config.ts +18 -3
  107. package/ignition/modules/lib/deps.ts +13 -0
  108. package/ignition/modules/test/tendecimals.ts +7 -1
  109. package/ignition/modules/zeto_anon.ts +3 -0
  110. package/ignition/modules/zeto_anon_burnable.ts +11 -7
  111. package/ignition/modules/zeto_anon_enc.ts +3 -0
  112. package/ignition/modules/zeto_anon_enc_nullifier.ts +34 -0
  113. package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +5 -2
  114. package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +3 -0
  115. package/ignition/modules/zeto_anon_nullifier.ts +31 -4
  116. package/ignition/modules/zeto_anon_nullifier_burnable.ts +53 -16
  117. package/ignition/modules/zeto_anon_nullifier_kyc.ts +30 -12
  118. package/ignition/modules/zeto_anon_nullifier_qurrency.ts +3 -0
  119. package/ignition/modules/zeto_nf_anon.ts +3 -1
  120. package/ignition/modules/zeto_nf_anon_nullifier.ts +17 -12
  121. package/package.json +7 -3
  122. package/scripts/deploy_cloneable.ts +19 -10
  123. package/scripts/deploy_upgradeable.ts +9 -5
  124. package/scripts/lib/zeto_libraries.ts +47 -0
  125. package/scripts/tokens/Zeto_Anon.ts +6 -3
  126. package/scripts/tokens/Zeto_AnonBurnable.ts +4 -1
  127. package/scripts/tokens/Zeto_AnonEnc.ts +15 -3
  128. package/scripts/tokens/Zeto_AnonEncNullifier.ts +11 -8
  129. package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +7 -6
  130. package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +7 -6
  131. package/scripts/tokens/Zeto_AnonNullifier.ts +7 -6
  132. package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +7 -6
  133. package/scripts/tokens/Zeto_AnonNullifierKyc.ts +7 -6
  134. package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +7 -8
  135. package/scripts/tokens/Zeto_NfAnon.ts +5 -3
  136. package/scripts/tokens/Zeto_NfAnonNullifier.ts +7 -7
  137. package/test/factory.ts +55 -73
  138. package/test/lib/anon_nullifier_helpers.ts +89 -0
  139. package/test/lib/anon_zeto_helpers.ts +76 -0
  140. package/test/lib/deploy.ts +5 -2
  141. package/test/lib/eip170.ts +23 -0
  142. package/test/lib/utils.ts +74 -35
  143. package/test/test/escrow1.ts +185 -58
  144. package/test/test/escrow2.ts +200 -107
  145. package/test/test/qurrency.ts +13 -33
  146. package/test/usdc-shielding.ts +39 -27
  147. package/test/utils.ts +144 -21
  148. package/test/zeto_anon.ts +956 -465
  149. package/test/zeto_anon_enc.ts +881 -143
  150. package/test/zeto_anon_enc_nullifier.ts +850 -39
  151. package/test/zeto_anon_enc_nullifier_kyc.ts +123 -182
  152. package/test/zeto_anon_enc_nullifier_non_repudiation.ts +80 -47
  153. package/test/zeto_anon_nullifier.ts +1212 -954
  154. package/test/zeto_anon_nullifier_kyc.ts +677 -656
  155. package/test/zeto_anon_nullifier_qurrency.ts +455 -307
  156. package/test/zeto_nf_anon.ts +737 -138
  157. package/test/zeto_nf_anon_nullifier.ts +876 -247
  158. package/contracts/lib/zeto_base.sol +0 -293
  159. package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
  160. package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
  161. package/contracts/lib/zeto_nullifier.sol +0 -340
  162. package/contracts/zkDvP.sol_ +0 -273
  163. package/test/zkDvP.ts_ +0 -455
  164. /package/contracts/lib/{common.sol → common/common.sol} +0 -0
@@ -0,0 +1,219 @@
1
+ // Copyright © 2024 Kaleido, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ pragma solidity ^0.8.27;
17
+
18
+ import {IZetoLockableCapability} from "./interfaces/IZetoLockableCapability.sol";
19
+ import {IZetoLockHooks} from "./interfaces/IZetoLockHooks.sol";
20
+ import {ILockableCapability} from "./interfaces/ILockableCapability.sol";
21
+ import {ZetoCommon} from "./zeto_common.sol";
22
+ import {ZetoLockableLib} from "./zeto_lockable_lib.sol";
23
+
24
+ /// @title ZetoLockable
25
+ /// @author Kaleido, Inc.
26
+ /// @dev Thin embedding layer for {IZetoLockableCapability}. Shared lock
27
+ /// lifecycle logic lives in the linked external {ZetoLockableLib};
28
+ /// this contract forwards interface entry points to the library and
29
+ /// exposes {IZetoLockHooks} callbacks for circuit-specific work in
30
+ /// descendants ({ZetoFungible}, {ZetoNonFungible}).
31
+ abstract contract ZetoLockable is
32
+ ZetoCommon,
33
+ IZetoLockableCapability,
34
+ IZetoLockHooks
35
+ {
36
+ modifier onlySelf() {
37
+ if (msg.sender != address(this)) {
38
+ revert NotSelf(msg.sender);
39
+ }
40
+ _;
41
+ }
42
+
43
+ /// @inheritdoc IZetoLockableCapability
44
+ function computeLockId(
45
+ bytes calldata createArgs
46
+ ) external view override returns (bytes32) {
47
+ return ZetoLockableLib.computeLockId(createArgs);
48
+ }
49
+
50
+ /// @inheritdoc IZetoLockableCapability
51
+ function computeSpendHash(
52
+ uint256[] calldata lockedInputs,
53
+ uint256[] calldata lockedOutputs,
54
+ uint256[] calldata outputs,
55
+ bytes calldata data
56
+ ) external pure override returns (bytes32) {
57
+ return
58
+ ZetoLockableLib.computeSpendHash(
59
+ lockedInputs,
60
+ lockedOutputs,
61
+ outputs,
62
+ data
63
+ );
64
+ }
65
+
66
+ /// @inheritdoc IZetoLockableCapability
67
+ function computeCancelHash(
68
+ uint256[] calldata lockedInputs,
69
+ uint256[] calldata lockedOutputs,
70
+ uint256[] calldata outputs,
71
+ bytes calldata data
72
+ ) external pure override returns (bytes32) {
73
+ return
74
+ ZetoLockableLib.computeCancelHash(
75
+ lockedInputs,
76
+ lockedOutputs,
77
+ outputs,
78
+ data
79
+ );
80
+ }
81
+
82
+ /// @inheritdoc ILockableCapability
83
+ function createLock(
84
+ bytes calldata createArgs,
85
+ bytes32 spendCommitment,
86
+ bytes32 cancelCommitment,
87
+ bytes calldata data
88
+ ) external override returns (bytes32) {
89
+ return
90
+ ZetoLockableLib.createLock(
91
+ createArgs,
92
+ spendCommitment,
93
+ cancelCommitment,
94
+ data
95
+ );
96
+ }
97
+
98
+ /// @inheritdoc ILockableCapability
99
+ function updateLock(
100
+ bytes32 lockId,
101
+ bytes calldata updateArgs,
102
+ bytes32 spendCommitment,
103
+ bytes32 cancelCommitment,
104
+ bytes calldata data
105
+ ) external override {
106
+ ZetoLockableLib.updateLock(
107
+ lockId,
108
+ updateArgs,
109
+ spendCommitment,
110
+ cancelCommitment,
111
+ data
112
+ );
113
+ }
114
+
115
+ /// @inheritdoc ILockableCapability
116
+ function delegateLock(
117
+ bytes32 lockId,
118
+ bytes calldata delegateArgs,
119
+ address newSpender,
120
+ bytes calldata data
121
+ ) external override {
122
+ ZetoLockableLib.delegateLock(
123
+ lockId,
124
+ delegateArgs,
125
+ newSpender,
126
+ data
127
+ );
128
+ }
129
+
130
+ /// @inheritdoc ILockableCapability
131
+ function spendLock(
132
+ bytes32 lockId,
133
+ bytes calldata spendArgs,
134
+ bytes calldata data
135
+ ) external override {
136
+ ZetoLockableLib.spendLock(lockId, spendArgs, data);
137
+ }
138
+
139
+ /// @inheritdoc ILockableCapability
140
+ function cancelLock(
141
+ bytes32 lockId,
142
+ bytes calldata cancelArgs,
143
+ bytes calldata data
144
+ ) external override {
145
+ ZetoLockableLib.cancelLock(lockId, cancelArgs, data);
146
+ }
147
+
148
+ /// @inheritdoc ILockableCapability
149
+ function getLock(
150
+ bytes32 lockId
151
+ ) external view override returns (LockInfo memory) {
152
+ return ZetoLockableLib.getLock(lockId);
153
+ }
154
+
155
+ /// @inheritdoc ILockableCapability
156
+ function isLockActive(
157
+ bytes32 lockId
158
+ ) external view override returns (bool) {
159
+ return ZetoLockableLib.isLockActive(lockId);
160
+ }
161
+
162
+ /// @inheritdoc ILockableCapability
163
+ function getLockContent(
164
+ bytes32 lockId
165
+ ) external view override returns (bytes memory content) {
166
+ return ZetoLockableLib.getLockContent(lockId);
167
+ }
168
+
169
+ /// @inheritdoc IZetoLockableCapability
170
+ function getLockedInputs(
171
+ bytes32 lockId
172
+ ) external view override returns (uint256[] memory lockedInputs) {
173
+ return ZetoLockableLib.getLockedInputs(lockId);
174
+ }
175
+
176
+ /// @inheritdoc ZetoCommon
177
+ function locked(uint256 utxo) public view override returns (bool, address) {
178
+ return ZetoLockableLib.locked(utxo);
179
+ }
180
+
181
+ /// @inheritdoc IZetoLockHooks
182
+ function zetoLockDoLockTransition(
183
+ ZetoCreateLockArgs calldata args
184
+ ) external override onlySelf {
185
+ _doLockTransition(args);
186
+ }
187
+
188
+ /// @inheritdoc IZetoLockHooks
189
+ function zetoLockTransferLocked(
190
+ bytes32 lockId,
191
+ uint256[] calldata lockedInputs,
192
+ uint256[] calldata lockedOutputs,
193
+ uint256[] calldata outputs,
194
+ bytes calldata proof,
195
+ bytes calldata data
196
+ ) external override onlySelf {
197
+ _transferLocked(
198
+ lockId,
199
+ lockedInputs,
200
+ lockedOutputs,
201
+ outputs,
202
+ proof,
203
+ data
204
+ );
205
+ }
206
+
207
+ function _doLockTransition(
208
+ ZetoCreateLockArgs calldata args
209
+ ) internal virtual;
210
+
211
+ function _transferLocked(
212
+ bytes32 lockId,
213
+ uint256[] calldata lockedInputs,
214
+ uint256[] calldata lockedOutputs,
215
+ uint256[] calldata outputs,
216
+ bytes calldata proof,
217
+ bytes calldata data
218
+ ) internal virtual;
219
+ }
@@ -0,0 +1,460 @@
1
+ // Copyright © 2024 Kaleido, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ pragma solidity ^0.8.27;
17
+
18
+ import {ILockableCapability} from "./interfaces/ILockableCapability.sol";
19
+ import {IZetoLockableCapability} from "./interfaces/IZetoLockableCapability.sol";
20
+ import {IZetoLockHooks} from "./interfaces/IZetoLockHooks.sol";
21
+ import {ZetoCommonStorage} from "./zeto_common.sol";
22
+ import {ZetoLockableStorage} from "./zeto_lockable_storage.sol";
23
+
24
+ /// @title ZetoLockableLib
25
+ /// @author Kaleido, Inc.
26
+ /// @dev External library holding the shared {IZetoLockableCapability} lock
27
+ /// lifecycle. Deploy once per chain and link into every Zeto token
28
+ /// implementation; logic runs in the token's storage context via
29
+ /// `DELEGATECALL`. Circuit-specific work is delegated back to the
30
+ /// embedding token through {IZetoLockHooks}.
31
+ library ZetoLockableLib {
32
+ /// @dev Domain-separation tag for spend-intent commitments.
33
+ bytes32 private constant _SPEND_HASH_DOMAIN =
34
+ keccak256("Zeto.spendCommitment.v1");
35
+
36
+ /// @dev Domain-separation tag for cancel-intent commitments.
37
+ bytes32 private constant _CANCEL_HASH_DOMAIN =
38
+ keccak256("Zeto.cancelCommitment.v1");
39
+
40
+ function computeLockId(
41
+ bytes calldata createArgs
42
+ ) public view returns (bytes32) {
43
+ IZetoLockableCapability.ZetoCreateLockArgs memory args = abi.decode(
44
+ createArgs,
45
+ (IZetoLockableCapability.ZetoCreateLockArgs)
46
+ );
47
+ return _computeLockId(args.txId);
48
+ }
49
+
50
+ function computeSpendHash(
51
+ uint256[] calldata lockedInputs,
52
+ uint256[] calldata lockedOutputs,
53
+ uint256[] calldata outputs,
54
+ bytes calldata data
55
+ ) public pure returns (bytes32) {
56
+ return
57
+ _buildUnlockHash(
58
+ lockedInputs,
59
+ lockedOutputs,
60
+ outputs,
61
+ data,
62
+ _SPEND_HASH_DOMAIN
63
+ );
64
+ }
65
+
66
+ function computeCancelHash(
67
+ uint256[] calldata lockedInputs,
68
+ uint256[] calldata lockedOutputs,
69
+ uint256[] calldata outputs,
70
+ bytes calldata data
71
+ ) public pure returns (bytes32) {
72
+ return
73
+ _buildUnlockHash(
74
+ lockedInputs,
75
+ lockedOutputs,
76
+ outputs,
77
+ data,
78
+ _CANCEL_HASH_DOMAIN
79
+ );
80
+ }
81
+
82
+ function createLock(
83
+ bytes calldata createArgs,
84
+ bytes32 spendCommitment,
85
+ bytes32 cancelCommitment,
86
+ bytes calldata data
87
+ ) public returns (bytes32) {
88
+ IZetoLockableCapability.ZetoCreateLockArgs memory args = abi.decode(
89
+ createArgs,
90
+ (IZetoLockableCapability.ZetoCreateLockArgs)
91
+ );
92
+
93
+ bytes32 lockId = _computeLockId(args.txId);
94
+ if (ZetoLockableStorage.layout().locks[lockId].owner != address(0)) {
95
+ revert IZetoLockableCapability.DuplicateLock(lockId);
96
+ }
97
+ _useTxId(args.txId);
98
+
99
+ IZetoLockHooks(address(this)).zetoLockDoLockTransition(args);
100
+
101
+ // Delegate projection must be set here (not in the hook): the hook
102
+ // runs as an external self-call where msg.sender is address(this).
103
+ setLockDelegates(args.lockedOutputs, msg.sender);
104
+
105
+ ZetoLockableStorage.ZetoLockInfo storage lock = ZetoLockableStorage
106
+ .layout()
107
+ .locks[lockId];
108
+ lock.owner = msg.sender;
109
+ lock.spender = msg.sender;
110
+ lock.spendCommitment = spendCommitment;
111
+ lock.cancelCommitment = cancelCommitment;
112
+ lock.lockedInputs = args.lockedOutputs;
113
+
114
+ emit ILockableCapability.LockCreated(
115
+ lockId,
116
+ msg.sender,
117
+ msg.sender,
118
+ spendCommitment,
119
+ cancelCommitment,
120
+ data
121
+ );
122
+ emit IZetoLockableCapability.ZetoLockCreated(
123
+ args.txId,
124
+ lockId,
125
+ msg.sender,
126
+ args.inputs,
127
+ args.outputs,
128
+ args.lockedOutputs,
129
+ args.proof,
130
+ data
131
+ );
132
+
133
+ return lockId;
134
+ }
135
+
136
+ function updateLock(
137
+ bytes32 lockId,
138
+ bytes calldata updateArgs,
139
+ bytes32 spendCommitment,
140
+ bytes32 cancelCommitment,
141
+ bytes calldata data
142
+ ) public {
143
+ _requireLockActive(lockId);
144
+ _requireLockOwner(lockId);
145
+
146
+ ZetoLockableStorage.ZetoLockInfo storage lock = ZetoLockableStorage
147
+ .layout()
148
+ .locks[lockId];
149
+ if (lock.spender != lock.owner) {
150
+ revert ILockableCapability.LockImmutable(lockId);
151
+ }
152
+
153
+ IZetoLockableCapability.ZetoUpdateLockArgs memory args = abi.decode(
154
+ updateArgs,
155
+ (IZetoLockableCapability.ZetoUpdateLockArgs)
156
+ );
157
+ _useTxId(args.txId);
158
+
159
+ lock.spendCommitment = spendCommitment;
160
+ lock.cancelCommitment = cancelCommitment;
161
+
162
+ emit ILockableCapability.LockUpdated(
163
+ lockId,
164
+ msg.sender,
165
+ spendCommitment,
166
+ cancelCommitment,
167
+ data
168
+ );
169
+ emit IZetoLockableCapability.ZetoLockUpdated(
170
+ args.txId,
171
+ lockId,
172
+ msg.sender,
173
+ data
174
+ );
175
+ }
176
+
177
+ function delegateLock(
178
+ bytes32 lockId,
179
+ bytes calldata delegateArgs,
180
+ address newSpender,
181
+ bytes calldata data
182
+ ) public {
183
+ _requireLockActive(lockId);
184
+ _requireLockSpender(lockId);
185
+
186
+ IZetoLockableCapability.ZetoDelegateLockArgs memory args = abi.decode(
187
+ delegateArgs,
188
+ (IZetoLockableCapability.ZetoDelegateLockArgs)
189
+ );
190
+ _useTxId(args.txId);
191
+
192
+ ZetoLockableStorage.ZetoLockInfo storage lock = ZetoLockableStorage
193
+ .layout()
194
+ .locks[lockId];
195
+ address previousSpender = lock.spender;
196
+ lock.spender = newSpender;
197
+
198
+ setLockDelegates(lock.lockedInputs, newSpender);
199
+
200
+ emit ILockableCapability.LockDelegated(
201
+ lockId,
202
+ previousSpender,
203
+ newSpender,
204
+ data
205
+ );
206
+ emit IZetoLockableCapability.ZetoLockDelegated(
207
+ args.txId,
208
+ lockId,
209
+ previousSpender,
210
+ newSpender,
211
+ data
212
+ );
213
+ }
214
+
215
+ function spendLock(
216
+ bytes32 lockId,
217
+ bytes calldata spendArgs,
218
+ bytes calldata data
219
+ ) public {
220
+ _requireLockActive(lockId);
221
+ _requireLockSpender(lockId);
222
+
223
+ IZetoLockableCapability.ZetoSpendLockArgs memory args = abi.decode(
224
+ spendArgs,
225
+ (IZetoLockableCapability.ZetoSpendLockArgs)
226
+ );
227
+
228
+ uint256[] memory lockedInputs = ZetoLockableStorage
229
+ .layout()
230
+ .locks[lockId]
231
+ .lockedInputs;
232
+ bytes32 expectedHash = ZetoLockableStorage
233
+ .layout()
234
+ .locks[lockId]
235
+ .spendCommitment;
236
+ _consumeLock(
237
+ lockId,
238
+ lockedInputs,
239
+ expectedHash,
240
+ _SPEND_HASH_DOMAIN,
241
+ args
242
+ );
243
+
244
+ emit ILockableCapability.LockSpent(lockId, msg.sender, data);
245
+ emit IZetoLockableCapability.ZetoLockSpent(
246
+ args.txId,
247
+ lockId,
248
+ msg.sender,
249
+ lockedInputs,
250
+ args.lockedOutputs,
251
+ args.outputs,
252
+ args.proof,
253
+ data
254
+ );
255
+ }
256
+
257
+ function cancelLock(
258
+ bytes32 lockId,
259
+ bytes calldata cancelArgs,
260
+ bytes calldata data
261
+ ) public {
262
+ _requireLockActive(lockId);
263
+ _requireLockSpender(lockId);
264
+
265
+ IZetoLockableCapability.ZetoSpendLockArgs memory args = abi.decode(
266
+ cancelArgs,
267
+ (IZetoLockableCapability.ZetoSpendLockArgs)
268
+ );
269
+
270
+ uint256[] memory lockedInputs = ZetoLockableStorage
271
+ .layout()
272
+ .locks[lockId]
273
+ .lockedInputs;
274
+ bytes32 expectedHash = ZetoLockableStorage
275
+ .layout()
276
+ .locks[lockId]
277
+ .cancelCommitment;
278
+ _consumeLock(
279
+ lockId,
280
+ lockedInputs,
281
+ expectedHash,
282
+ _CANCEL_HASH_DOMAIN,
283
+ args
284
+ );
285
+
286
+ emit ILockableCapability.LockCancelled(lockId, msg.sender, data);
287
+ emit IZetoLockableCapability.ZetoLockCancelled(
288
+ args.txId,
289
+ lockId,
290
+ msg.sender,
291
+ lockedInputs,
292
+ args.lockedOutputs,
293
+ args.outputs,
294
+ args.proof,
295
+ data
296
+ );
297
+ }
298
+
299
+ function getLock(
300
+ bytes32 lockId
301
+ ) public view returns (ILockableCapability.LockInfo memory) {
302
+ _requireLockActive(lockId);
303
+ ZetoLockableStorage.ZetoLockInfo storage lock = ZetoLockableStorage
304
+ .layout()
305
+ .locks[lockId];
306
+ return
307
+ ILockableCapability.LockInfo({
308
+ owner: lock.owner,
309
+ spender: lock.spender,
310
+ spendCommitment: lock.spendCommitment,
311
+ cancelCommitment: lock.cancelCommitment
312
+ });
313
+ }
314
+
315
+ function isLockActive(bytes32 lockId) public view returns (bool) {
316
+ return ZetoLockableStorage.layout().locks[lockId].owner != address(0);
317
+ }
318
+
319
+ function getLockContent(
320
+ bytes32 lockId
321
+ ) public view returns (bytes memory content) {
322
+ _requireLockActive(lockId);
323
+ return
324
+ abi.encode(ZetoLockableStorage.layout().locks[lockId].lockedInputs);
325
+ }
326
+
327
+ function getLockedInputs(
328
+ bytes32 lockId
329
+ ) public view returns (uint256[] memory lockedInputs) {
330
+ _requireLockActive(lockId);
331
+ return ZetoLockableStorage.layout().locks[lockId].lockedInputs;
332
+ }
333
+
334
+ function locked(uint256 utxo) public view returns (bool, address) {
335
+ if (!ZetoCommonStorage.layout().utxoStorage.locked(utxo)) {
336
+ return (false, address(0));
337
+ }
338
+ return (true, ZetoLockableStorage.layout().utxoDelegates[utxo]);
339
+ }
340
+
341
+ function setLockDelegates(
342
+ uint256[] memory utxos,
343
+ address spender
344
+ ) public {
345
+ for (uint256 i = 0; i < utxos.length; ++i) {
346
+ if (utxos[i] != 0) {
347
+ ZetoLockableStorage.layout().utxoDelegates[utxos[i]] = spender;
348
+ }
349
+ }
350
+ }
351
+
352
+ function _computeLockId(bytes32 txId) private view returns (bytes32) {
353
+ return keccak256(abi.encode(address(this), msg.sender, txId));
354
+ }
355
+
356
+ function _useTxId(bytes32 txId) private {
357
+ if (ZetoLockableStorage.layout().txIds[msg.sender][txId]) {
358
+ revert IZetoLockableCapability.DuplicateTransaction(txId);
359
+ }
360
+ ZetoLockableStorage.layout().txIds[msg.sender][txId] = true;
361
+ }
362
+
363
+ function _requireLockActive(bytes32 lockId) private view {
364
+ if (ZetoLockableStorage.layout().locks[lockId].owner == address(0)) {
365
+ revert ILockableCapability.LockNotActive(lockId);
366
+ }
367
+ }
368
+
369
+ function _requireLockOwner(bytes32 lockId) private view {
370
+ address owner = ZetoLockableStorage.layout().locks[lockId].owner;
371
+ if (owner != msg.sender) {
372
+ revert ILockableCapability.LockUnauthorized(
373
+ lockId,
374
+ owner,
375
+ msg.sender
376
+ );
377
+ }
378
+ }
379
+
380
+ function _requireLockSpender(bytes32 lockId) private view {
381
+ address spender = ZetoLockableStorage.layout().locks[lockId].spender;
382
+ if (spender != msg.sender) {
383
+ revert ILockableCapability.LockUnauthorized(
384
+ lockId,
385
+ spender,
386
+ msg.sender
387
+ );
388
+ }
389
+ }
390
+
391
+ function _consumeLock(
392
+ bytes32 lockId,
393
+ uint256[] memory lockedInputs,
394
+ bytes32 expectedHash,
395
+ bytes32 hashDomain,
396
+ IZetoLockableCapability.ZetoSpendLockArgs memory args
397
+ ) private {
398
+ _useTxId(args.txId);
399
+
400
+ if (expectedHash != 0) {
401
+ bytes32 actualHash = _buildUnlockHash(
402
+ lockedInputs,
403
+ args.lockedOutputs,
404
+ args.outputs,
405
+ args.data,
406
+ hashDomain
407
+ );
408
+ if (actualHash != expectedHash) {
409
+ revert IZetoLockableCapability.InvalidUnlockHash(
410
+ expectedHash,
411
+ actualHash
412
+ );
413
+ }
414
+ }
415
+
416
+ _clearLockDelegates(lockedInputs);
417
+ delete ZetoLockableStorage.layout().locks[lockId];
418
+
419
+ IZetoLockHooks(address(this)).zetoLockTransferLocked(
420
+ lockId,
421
+ lockedInputs,
422
+ args.lockedOutputs,
423
+ args.outputs,
424
+ args.proof,
425
+ args.data
426
+ );
427
+
428
+ // Same msg.sender rationale as {createLock}: hook is external self-call.
429
+ if (args.lockedOutputs.length > 0) {
430
+ setLockDelegates(args.lockedOutputs, msg.sender);
431
+ }
432
+ }
433
+
434
+ function _clearLockDelegates(uint256[] memory utxos) private {
435
+ for (uint256 i = 0; i < utxos.length; ++i) {
436
+ if (utxos[i] != 0) {
437
+ delete ZetoLockableStorage.layout().utxoDelegates[utxos[i]];
438
+ }
439
+ }
440
+ }
441
+
442
+ function _buildUnlockHash(
443
+ uint256[] memory lockedInputs,
444
+ uint256[] memory lockedOutputs,
445
+ uint256[] memory outputs,
446
+ bytes memory data,
447
+ bytes32 domain
448
+ ) private pure returns (bytes32) {
449
+ return
450
+ keccak256(
451
+ abi.encode(
452
+ domain,
453
+ keccak256(abi.encode(lockedInputs)),
454
+ keccak256(abi.encode(lockedOutputs)),
455
+ keccak256(abi.encode(outputs)),
456
+ keccak256(data)
457
+ )
458
+ );
459
+ }
460
+ }