@lfdecentralizedtrust/zeto-contracts 0.5.0 → 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 (50) hide show
  1. package/README.md +6 -0
  2. package/config/eip170.ts +30 -0
  3. package/contracts/lib/interfaces/IZetoLockHooks.sol +42 -0
  4. package/contracts/lib/zeto_fungible.sol +9 -17
  5. package/contracts/lib/zeto_lockable.sol +85 -479
  6. package/contracts/lib/zeto_lockable_lib.sol +460 -0
  7. package/contracts/lib/zeto_lockable_storage.sol +43 -0
  8. package/contracts/lib/zeto_non_fungible.sol +8 -16
  9. package/hardhat.config.ts +11 -2
  10. package/ignition/modules/lib/deps.ts +5 -0
  11. package/ignition/modules/test/tendecimals.ts +7 -1
  12. package/ignition/modules/zeto_anon.ts +3 -0
  13. package/ignition/modules/zeto_anon_burnable.ts +3 -0
  14. package/ignition/modules/zeto_anon_enc.ts +3 -0
  15. package/ignition/modules/zeto_anon_enc_nullifier.ts +3 -0
  16. package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +3 -0
  17. package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +3 -0
  18. package/ignition/modules/zeto_anon_nullifier.ts +3 -0
  19. package/ignition/modules/zeto_anon_nullifier_burnable.ts +3 -0
  20. package/ignition/modules/zeto_anon_nullifier_kyc.ts +3 -0
  21. package/ignition/modules/zeto_anon_nullifier_qurrency.ts +3 -0
  22. package/ignition/modules/zeto_nf_anon.ts +3 -1
  23. package/ignition/modules/zeto_nf_anon_nullifier.ts +3 -2
  24. package/package.json +4 -2
  25. package/scripts/lib/zeto_libraries.ts +47 -0
  26. package/scripts/tokens/Zeto_Anon.ts +3 -0
  27. package/scripts/tokens/Zeto_AnonBurnable.ts +3 -0
  28. package/scripts/tokens/Zeto_AnonEnc.ts +3 -0
  29. package/scripts/tokens/Zeto_AnonEncNullifier.ts +6 -5
  30. package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +6 -5
  31. package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +6 -5
  32. package/scripts/tokens/Zeto_AnonNullifier.ts +6 -5
  33. package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +6 -5
  34. package/scripts/tokens/Zeto_AnonNullifierKyc.ts +6 -5
  35. package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +6 -7
  36. package/scripts/tokens/Zeto_NfAnon.ts +3 -1
  37. package/scripts/tokens/Zeto_NfAnonNullifier.ts +6 -6
  38. package/test/factory.ts +10 -1
  39. package/test/lib/deploy.ts +2 -0
  40. package/test/lib/eip170.ts +23 -0
  41. package/test/usdc-shielding.ts +0 -1
  42. package/test/zeto_anon_enc.ts +0 -1
  43. package/test/zeto_anon_enc_nullifier.ts +3 -1
  44. package/test/zeto_anon_enc_nullifier_kyc.ts +3 -1
  45. package/test/zeto_anon_enc_nullifier_non_repudiation.ts +3 -1
  46. package/test/zeto_anon_nullifier.ts +0 -1
  47. package/test/zeto_anon_nullifier_kyc.ts +3 -1
  48. package/test/zeto_anon_nullifier_qurrency.ts +3 -1
  49. package/test/zeto_nf_anon.ts +0 -1
  50. package/test/zeto_nf_anon_nullifier.ts +0 -1
package/README.md CHANGED
@@ -13,6 +13,10 @@ Privacy-preserving token implementations for fungible and non-fungible assets, b
13
13
 
14
14
  Hardhat and related tooling are pulled in via `@nomicfoundation/hardhat-toolbox`; you do not need to run `hardhat init` in this repository.
15
15
 
16
+ ### Contract size (EIP-170)
17
+
18
+ Mainnet limits deployed bytecode to **24,576 bytes**. This repo enforces that on the Hardhat network and at compile time via `hardhat-contract-sizer`. Run `npm run size` to print sizes after compile.
19
+
16
20
  ### Circuits and proving keys
17
21
 
18
22
  Hardhat tests load circuit WASM via **`zeto-js`** (`file:../zkp/js`). Before running tests:
@@ -74,6 +78,8 @@ npx hardhat run scripts/deploy_cloneable.ts
74
78
 
75
79
  This deploys the **implementation only**. Leaf tokens lock the impl with `_disableInitializers()`; **`initialize` runs on proxies** created by **`ZetoTokenFactory`**. Tests use **`USE_FACTORY=true`** in `test/lib/deploy.ts` to register the impl and deploy initialized clones. Running the script **by itself** does not yield a ready-to-use initialized token unless you finish that factory flow.
76
80
 
81
+ Every token implementation links the external **`ZetoLockableLib`** library (deployed once per chain via Ignition). Token deploy scripts in `scripts/tokens/` pass it in the `libraries` map alongside `SmtLib` / Poseidon where applicable.
82
+
77
83
  For a single initialized deployment without the factory path, use **`deploy_upgradeable.ts`**.
78
84
 
79
85
  Cheap repeat deployments: OpenZeppelin [minimal proxies / Clones](https://docs.openzeppelin.com/contracts/5.x/api/utils#Clones).
@@ -0,0 +1,30 @@
1
+ /**
2
+ * EIP-170 (Spurious Dragon) maximum deployed runtime bytecode size.
3
+ * @see https://eips.ethereum.org/EIPS/eip-170
4
+ */
5
+ export const EIP170_BYTE_LIMIT = 24_576;
6
+
7
+ /**
8
+ * Contracts that currently exceed EIP170_BYTE_LIMIT with the compiler settings
9
+ * in hardhat.config.ts. Exempt from `hardhat-contract-sizer` strict checks
10
+ * until further library splits land.
11
+ *
12
+ * Remove names from this list as implementations are brought under the limit.
13
+ */
14
+ export const EIP170_EXEMPT_CONTRACTS: readonly string[] = [
15
+ "Zeto_AnonEncNullifier",
16
+ "Zeto_AnonEncNullifierKyc",
17
+ "Zeto_AnonEncNullifierNonRepudiation",
18
+ "Zeto_AnonNullifierBurnable",
19
+ "Zeto_AnonNullifierQurrency",
20
+ "Groth16Verifier_AnonEncNullifierNonRepudiationBatch",
21
+ ] as const;
22
+
23
+ export const EIP170_EXEMPT_CONTRACTS_SET = new Set<string>(
24
+ EIP170_EXEMPT_CONTRACTS,
25
+ );
26
+
27
+ /** Token implementations in the exemption list (excludes standalone verifiers). */
28
+ export const EIP170_EXEMPT_TOKEN_SET = new Set<string>(
29
+ EIP170_EXEMPT_CONTRACTS.filter((name) => name.startsWith("Zeto_")),
30
+ );
@@ -0,0 +1,42 @@
1
+ // Copyright © 2025 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 "./IZetoLockableCapability.sol";
19
+
20
+ /**
21
+ * @title IZetoLockHooks
22
+ * @dev Callback surface invoked by {ZetoLockableLib} (via `address(this)`)
23
+ * so circuit-specific lock transitions stay in the embedding token
24
+ * while shared lock lifecycle logic lives in the external library.
25
+ */
26
+ interface IZetoLockHooks {
27
+ /// @dev Thrown when a hook is invoked by an address other than `address(this)`.
28
+ error NotSelf(address caller);
29
+
30
+ function zetoLockDoLockTransition(
31
+ IZetoLockableCapability.ZetoCreateLockArgs calldata args
32
+ ) external;
33
+
34
+ function zetoLockTransferLocked(
35
+ bytes32 lockId,
36
+ uint256[] calldata lockedInputs,
37
+ uint256[] calldata lockedOutputs,
38
+ uint256[] calldata outputs,
39
+ bytes calldata proof,
40
+ bytes calldata data
41
+ ) external;
42
+ }
@@ -30,9 +30,9 @@ import {IZetoStorage} from "./interfaces/IZetoStorage.sol";
30
30
  /// @dev Adds the ERC20-backed deposit/withdraw lifecycle and a multi-input
31
31
  /// {transfer} flow on top of the lock-aware {ZetoLockable} base.
32
32
  ///
33
- /// The lock-lifecycle plumbing (state, modifiers, external entry
34
- /// points, views) lives in {ZetoLockable}; this contract supplies
35
- /// only the two ZK-circuit-shaped hooks
33
+ /// The lock-lifecycle plumbing (state, external entry points, views)
34
+ /// lives in the linked external {ZetoLockableLib}; this contract
35
+ /// supplies only the two ZK-circuit-shaped hooks
36
36
  /// ({_doLockTransition} and {_transferLocked}) that pad
37
37
  /// inputs/outputs to the next supported batch size before
38
38
  /// {constructPublicInputs}.
@@ -162,7 +162,7 @@ abstract contract ZetoFungible is ZetoLockable, ReentrancyGuardUpgradeable {
162
162
  // ------------------------------------------------------------------
163
163
 
164
164
  function _doLockTransition(
165
- ZetoCreateLockArgs memory args
165
+ ZetoCreateLockArgs calldata args
166
166
  ) internal override {
167
167
  validateTransactionProposal(
168
168
  args.inputs,
@@ -206,19 +206,15 @@ abstract contract ZetoFungible is ZetoLockable, ReentrancyGuardUpgradeable {
206
206
 
207
207
  processInputsAndOutputs(paddedInputs, args.outputs, false);
208
208
  processLockedOutputs(args.lockedOutputs);
209
- // The freshly-locked outputs all start under the lock creator
210
- // as both owner and spender; record that on the per-UTXO
211
- // projection so {locked} can report it without a reverse lookup.
212
- _setLockDelegates(args.lockedOutputs, msg.sender);
213
209
  }
214
210
 
215
211
  function _transferLocked(
216
212
  bytes32 /* lockId */,
217
- uint256[] memory lockedInputs,
218
- uint256[] memory lockedOutputs,
219
- uint256[] memory outputs,
220
- bytes memory proof,
221
- bytes memory /* data */
213
+ uint256[] calldata lockedInputs,
214
+ uint256[] calldata lockedOutputs,
215
+ uint256[] calldata outputs,
216
+ bytes calldata proof,
217
+ bytes calldata /* data */
222
218
  ) internal override {
223
219
  validateTransactionProposal(
224
220
  lockedInputs,
@@ -253,10 +249,6 @@ abstract contract ZetoFungible is ZetoLockable, ReentrancyGuardUpgradeable {
253
249
  verifyProof(proofStruct, publicInputs, isBatch, true);
254
250
  processInputsAndOutputs(paddedInputs, paddedOutputs, true);
255
251
  processLockedOutputs(lockedOutputs);
256
- // Any newly-locked outputs produced by this spend default to the
257
- // current spender as their delegate. (When `lockedOutputs` is
258
- // empty -- the common case -- this is a no-op.)
259
- _setLockDelegates(lockedOutputs, msg.sender);
260
252
  }
261
253
 
262
254
  /**