@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.
- package/README.md +76 -162
- package/config/eip170.ts +30 -0
- package/contracts/factory.sol +30 -34
- package/contracts/factory_upgradeable.sol +11 -7
- package/contracts/lib/common/util.sol +40 -0
- package/contracts/lib/interfaces/ILockableCapability.sol +318 -0
- package/contracts/lib/interfaces/{izeto.sol → IZeto.sol} +13 -1
- package/contracts/lib/interfaces/{izeto_initializable.sol → IZetoInitializable.sol} +14 -12
- package/contracts/lib/interfaces/{izeto_kyc.sol → IZetoKyc.sol} +3 -3
- package/contracts/lib/interfaces/IZetoLockHooks.sol +42 -0
- package/contracts/lib/interfaces/IZetoLockableCapability.sol +237 -0
- package/contracts/lib/interfaces/IZetoStorage.sol +106 -0
- package/contracts/lib/interfaces/{izeto_lockable.sol → IZetoVerifier.sol} +8 -21
- package/contracts/lib/registry.sol +74 -26
- package/contracts/lib/storage/base.sol +210 -0
- package/contracts/lib/storage/nullifier.sol +166 -0
- package/contracts/lib/zeto_common.sol +277 -28
- package/contracts/lib/zeto_fungible.sol +443 -33
- package/contracts/lib/zeto_fungible_base.sol +69 -0
- package/contracts/lib/zeto_fungible_burn.sol +83 -53
- package/contracts/lib/zeto_fungible_burn_nullifier.sol +115 -72
- package/contracts/lib/zeto_fungible_nullifier.sol +167 -0
- package/contracts/lib/zeto_lockable.sol +219 -0
- package/contracts/lib/zeto_lockable_lib.sol +460 -0
- package/contracts/lib/zeto_lockable_storage.sol +43 -0
- package/contracts/lib/zeto_non_fungible.sol +228 -0
- package/contracts/lib/zeto_non_fungible_base.sol +61 -0
- package/contracts/lib/zeto_non_fungible_nullifier.sol +61 -0
- package/contracts/test/escrow1.sol +90 -34
- package/contracts/test/escrow2.sol +64 -29
- package/contracts/test/qurrency.sol +10 -2
- package/contracts/test/smt.sol +6 -1
- package/contracts/test/tendecimals.sol +14 -12
- package/contracts/verifiers/impl/anon.sol +189 -0
- package/contracts/verifiers/impl/anon_batch.sol +301 -0
- package/contracts/verifiers/impl/anon_enc.sol +266 -0
- package/contracts/verifiers/impl/anon_enc_batch.sol +602 -0
- package/contracts/verifiers/impl/anon_enc_nullifier.sol +287 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_batch.sol +679 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc.sol +294 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc_batch.sol +686 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation.sol +413 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation_batch.sol +1141 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer.sol +217 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked.sol +196 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked_batch.sol +308 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer_batch.sol +385 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer.sol +497 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer_batch.sol +1001 -0
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked.sol → impl/anon_nullifier_transfer.sol} +12 -19
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked_batch.sol → impl/anon_nullifier_transfer_batch.sol} +44 -51
- package/contracts/verifiers/impl/burn.sol +182 -0
- package/contracts/verifiers/impl/burn_batch.sol +238 -0
- package/contracts/verifiers/impl/burn_nullifier.sol +203 -0
- package/contracts/verifiers/impl/burn_nullifier_batch.sol +315 -0
- package/contracts/verifiers/impl/deposit.sol +182 -0
- package/contracts/verifiers/impl/deposit_kyc.sol +189 -0
- package/contracts/verifiers/impl/nf_anon.sol +175 -0
- package/contracts/verifiers/{verifier_nf_anon_nullifier_transferLocked.sol → impl/nf_anon_nullifier_transfer.sol} +6 -13
- package/contracts/verifiers/impl/withdraw.sol +189 -0
- package/contracts/verifiers/impl/withdraw_batch.sol +245 -0
- package/contracts/verifiers/impl/withdraw_nullifier.sol +210 -0
- package/contracts/verifiers/impl/withdraw_nullifier_batch.sol +322 -0
- package/contracts/verifiers/verifier_anon.sol +31 -186
- package/contracts/verifiers/verifier_anon_batch.sol +31 -298
- package/contracts/verifiers/verifier_anon_enc.sol +31 -263
- package/contracts/verifiers/verifier_anon_enc_batch.sol +31 -599
- package/contracts/verifiers/verifier_anon_enc_nullifier.sol +31 -284
- package/contracts/verifiers/verifier_anon_enc_nullifier_batch.sol +33 -676
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc.sol +31 -291
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc_batch.sol +33 -683
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation.sol +33 -410
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation_batch.sol +33 -1138
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer.sol +33 -214
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer_batch.sol +33 -382
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_transfer.sol +33 -207
- package/contracts/verifiers/verifier_anon_nullifier_transfer_batch.sol +33 -375
- package/contracts/verifiers/verifier_burn.sol +31 -179
- package/contracts/verifiers/verifier_burn_batch.sol +31 -235
- package/contracts/verifiers/verifier_burn_nullifier.sol +31 -200
- package/contracts/verifiers/verifier_burn_nullifier_batch.sol +31 -312
- package/contracts/verifiers/verifier_deposit.sol +31 -179
- package/contracts/verifiers/verifier_deposit_kyc.sol +34 -0
- package/contracts/verifiers/verifier_nf_anon.sol +31 -172
- package/contracts/verifiers/verifier_nf_anon_nullifier_transfer.sol +33 -179
- package/contracts/verifiers/verifier_withdraw.sol +31 -186
- package/contracts/verifiers/verifier_withdraw_batch.sol +31 -242
- package/contracts/verifiers/verifier_withdraw_nullifier.sol +31 -207
- package/contracts/verifiers/verifier_withdraw_nullifier_batch.sol +33 -319
- package/contracts/zeto_anon.sol +77 -231
- package/contracts/zeto_anon_burnable.sol +56 -12
- package/contracts/zeto_anon_enc.sol +93 -190
- package/contracts/zeto_anon_enc_nullifier.sol +249 -195
- package/contracts/zeto_anon_enc_nullifier_kyc.sol +51 -232
- package/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +231 -238
- package/contracts/zeto_anon_nullifier.sol +164 -298
- package/contracts/zeto_anon_nullifier_burnable.sol +68 -18
- package/contracts/zeto_anon_nullifier_kyc.sol +40 -345
- package/contracts/zeto_anon_nullifier_qurrency.sol +217 -361
- package/contracts/zeto_nf_anon.sol +55 -130
- package/contracts/zeto_nf_anon_nullifier.sol +90 -152
- package/hardhat.config.ts +18 -3
- package/ignition/modules/lib/deps.ts +13 -0
- package/ignition/modules/test/tendecimals.ts +7 -1
- package/ignition/modules/zeto_anon.ts +3 -0
- package/ignition/modules/zeto_anon_burnable.ts +11 -7
- package/ignition/modules/zeto_anon_enc.ts +3 -0
- package/ignition/modules/zeto_anon_enc_nullifier.ts +34 -0
- package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +5 -2
- package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +3 -0
- package/ignition/modules/zeto_anon_nullifier.ts +31 -4
- package/ignition/modules/zeto_anon_nullifier_burnable.ts +53 -16
- package/ignition/modules/zeto_anon_nullifier_kyc.ts +30 -12
- package/ignition/modules/zeto_anon_nullifier_qurrency.ts +3 -0
- package/ignition/modules/zeto_nf_anon.ts +3 -1
- package/ignition/modules/zeto_nf_anon_nullifier.ts +17 -12
- package/package.json +7 -3
- package/scripts/deploy_cloneable.ts +19 -10
- package/scripts/deploy_upgradeable.ts +9 -5
- package/scripts/lib/zeto_libraries.ts +47 -0
- package/scripts/tokens/Zeto_Anon.ts +6 -3
- package/scripts/tokens/Zeto_AnonBurnable.ts +4 -1
- package/scripts/tokens/Zeto_AnonEnc.ts +15 -3
- package/scripts/tokens/Zeto_AnonEncNullifier.ts +11 -8
- package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifier.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +7 -8
- package/scripts/tokens/Zeto_NfAnon.ts +5 -3
- package/scripts/tokens/Zeto_NfAnonNullifier.ts +7 -7
- package/test/factory.ts +55 -73
- package/test/lib/anon_nullifier_helpers.ts +89 -0
- package/test/lib/anon_zeto_helpers.ts +76 -0
- package/test/lib/deploy.ts +5 -2
- package/test/lib/eip170.ts +23 -0
- package/test/lib/utils.ts +74 -35
- package/test/test/escrow1.ts +185 -58
- package/test/test/escrow2.ts +200 -107
- package/test/test/qurrency.ts +13 -33
- package/test/usdc-shielding.ts +39 -27
- package/test/utils.ts +144 -21
- package/test/zeto_anon.ts +956 -465
- package/test/zeto_anon_enc.ts +881 -143
- package/test/zeto_anon_enc_nullifier.ts +850 -39
- package/test/zeto_anon_enc_nullifier_kyc.ts +123 -182
- package/test/zeto_anon_enc_nullifier_non_repudiation.ts +80 -47
- package/test/zeto_anon_nullifier.ts +1212 -954
- package/test/zeto_anon_nullifier_kyc.ts +677 -656
- package/test/zeto_anon_nullifier_qurrency.ts +455 -307
- package/test/zeto_nf_anon.ts +737 -138
- package/test/zeto_nf_anon_nullifier.ts +876 -247
- package/contracts/lib/zeto_base.sol +0 -293
- package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
- package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
- package/contracts/lib/zeto_nullifier.sol +0 -340
- package/contracts/zkDvP.sol_ +0 -273
- package/test/zkDvP.ts_ +0 -455
- /package/contracts/lib/{common.sol → common/common.sol} +0 -0
|
@@ -15,72 +15,102 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
pragma solidity ^0.8.27;
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {Commonlib} from "./common.sol";
|
|
22
|
-
|
|
23
|
-
uint256 constant BURN_INPUT_SIZE = 3;
|
|
24
|
-
uint256 constant BATCH_BURN_INPUT_SIZE = 11;
|
|
18
|
+
import {IGroth16Verifier} from "./interfaces/IZetoVerifier.sol";
|
|
19
|
+
import {ZetoFungibleBase} from "./zeto_fungible_base.sol";
|
|
20
|
+
import {Commonlib} from "./common/common.sol";
|
|
25
21
|
|
|
26
22
|
/// @title A feature implementation of a Zeto fungible token burn contract
|
|
27
23
|
/// @author Kaleido, Inc.
|
|
28
|
-
/// @dev
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
/// @dev Mixed-in alongside {ZetoFungibleBase} (the non-nullifier sibling of
|
|
25
|
+
/// {ZetoFungibleNullifier}) to add a {burn} entry point that destroys a
|
|
26
|
+
/// set of input UTXOs and produces a single output UTXO holding the
|
|
27
|
+
/// remainder. The burn proof attests that the inputs sum to
|
|
28
|
+
/// `output + burn_amount` while preserving owner-side range and
|
|
29
|
+
/// ownership invariants.
|
|
30
|
+
///
|
|
31
|
+
/// The locking lifecycle is unaffected by burning: locked UTXOs cannot
|
|
32
|
+
/// be supplied as inputs because {validateInputs} (called from {_burn})
|
|
33
|
+
/// rejects locked entries via the underlying {BaseStorage} ledger.
|
|
34
|
+
abstract contract ZetoFungibleBurnable is ZetoFungibleBase {
|
|
35
|
+
/// @dev Internal-only so it can only be called from a derived
|
|
36
|
+
/// contract's own `initializer`-guarded entrypoint.
|
|
33
37
|
function __ZetoFungibleBurnable_init(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
IGroth16Verifier burnVerifier,
|
|
39
|
+
IGroth16Verifier batchBurnVerifier
|
|
40
|
+
) internal onlyInitializing {
|
|
41
|
+
ZetoFungibleBurnableStorage.Layout storage $ = ZetoFungibleBurnableStorage
|
|
42
|
+
.layout();
|
|
43
|
+
$.burnVerifier = burnVerifier;
|
|
44
|
+
$.batchBurnVerifier = batchBurnVerifier;
|
|
39
45
|
}
|
|
40
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @dev Burn a set of inputs, leaving a single output UTXO that holds the
|
|
49
|
+
* remainder.
|
|
50
|
+
* @param inputs The input UTXOs to burn.
|
|
51
|
+
* @param output The single output UTXO holding the remainder.
|
|
52
|
+
* @param proof The Groth16 proof attesting to value conservation and
|
|
53
|
+
* owner-side range/ownership invariants.
|
|
54
|
+
* @param data Opaque data appended to the {UTXOBurn} event for off-chain
|
|
55
|
+
* consumers (e.g. correlation ids).
|
|
56
|
+
*
|
|
57
|
+
* Emits a {UTXOBurn} event.
|
|
58
|
+
*/
|
|
41
59
|
function burn(
|
|
42
|
-
uint256[]
|
|
60
|
+
uint256[] calldata inputs,
|
|
43
61
|
uint256 output,
|
|
44
62
|
Commonlib.Proof calldata proof,
|
|
45
63
|
bytes calldata data
|
|
46
64
|
) public virtual {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
proof.pC,
|
|
61
|
-
fixedSizeInputs
|
|
62
|
-
),
|
|
63
|
-
"Invalid proof"
|
|
64
|
-
);
|
|
65
|
-
} else {
|
|
66
|
-
// construct the public inputs for verifier
|
|
67
|
-
uint256[BURN_INPUT_SIZE] memory fixedSizeInputs;
|
|
68
|
-
for (uint256 i = 0; i < inputs.length; i++) {
|
|
69
|
-
fixedSizeInputs[i] = inputs[i];
|
|
70
|
-
}
|
|
71
|
-
fixedSizeInputs[BURN_INPUT_SIZE - 1] = output;
|
|
72
|
-
// Check the proof
|
|
73
|
-
require(
|
|
74
|
-
_burnVerifier.verifyProof(
|
|
75
|
-
proof.pA,
|
|
76
|
-
proof.pB,
|
|
77
|
-
proof.pC,
|
|
78
|
-
fixedSizeInputs
|
|
79
|
-
),
|
|
80
|
-
"Invalid proof"
|
|
81
|
-
);
|
|
65
|
+
uint256[] memory publicInputs = new uint256[](inputs.length + 1);
|
|
66
|
+
for (uint256 i = 0; i < inputs.length; i++) {
|
|
67
|
+
publicInputs[i] = inputs[i];
|
|
68
|
+
}
|
|
69
|
+
publicInputs[inputs.length] = output;
|
|
70
|
+
|
|
71
|
+
ZetoFungibleBurnableStorage.Layout storage $ = ZetoFungibleBurnableStorage
|
|
72
|
+
.layout();
|
|
73
|
+
IGroth16Verifier verifier = (inputs.length > 2)
|
|
74
|
+
? $.batchBurnVerifier
|
|
75
|
+
: $.burnVerifier;
|
|
76
|
+
if (!verifier.verify(proof.pA, proof.pB, proof.pC, publicInputs)) {
|
|
77
|
+
revert InvalidProof();
|
|
82
78
|
}
|
|
83
79
|
|
|
84
80
|
_burn(inputs, output, data);
|
|
85
81
|
}
|
|
82
|
+
|
|
83
|
+
/// @dev Validate inputs/outputs, then transition state and emit the
|
|
84
|
+
/// {UTXOBurn} event. Marked virtual so concrete tokens can wrap
|
|
85
|
+
/// with additional bookkeeping if needed.
|
|
86
|
+
function _burn(
|
|
87
|
+
uint256[] memory inputs,
|
|
88
|
+
uint256 output,
|
|
89
|
+
bytes calldata data
|
|
90
|
+
) internal virtual {
|
|
91
|
+
validateInputs(inputs, false);
|
|
92
|
+
uint256[] memory outputStates = new uint256[](1);
|
|
93
|
+
outputStates[0] = output;
|
|
94
|
+
validateOutputs(outputStates);
|
|
95
|
+
processInputs(inputs, false);
|
|
96
|
+
processOutputs(outputStates);
|
|
97
|
+
emit UTXOBurn(inputs, output, msg.sender, data);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// @dev ERC-7201 (`erc7201:zeto.storage.ZetoFungibleBurnable`).
|
|
102
|
+
library ZetoFungibleBurnableStorage {
|
|
103
|
+
struct Layout {
|
|
104
|
+
IGroth16Verifier burnVerifier;
|
|
105
|
+
IGroth16Verifier batchBurnVerifier;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
bytes32 private constant STORAGE_LOCATION =
|
|
109
|
+
0x99d1a11894f655177598fbad145350332923053ddb779beb1721e5203b8acf00;
|
|
110
|
+
|
|
111
|
+
function layout() internal pure returns (Layout storage $) {
|
|
112
|
+
assembly {
|
|
113
|
+
$.slot := STORAGE_LOCATION
|
|
114
|
+
}
|
|
115
|
+
}
|
|
86
116
|
}
|
|
@@ -15,30 +15,49 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
pragma solidity ^0.8.27;
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {Commonlib} from "./common.sol";
|
|
18
|
+
import {IGroth16Verifier} from "./interfaces/IZetoVerifier.sol";
|
|
19
|
+
import {ZetoFungibleNullifier} from "./zeto_fungible_nullifier.sol";
|
|
20
|
+
import {Commonlib} from "./common/common.sol";
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
uint256 constant BATCH_BURN_INPUT_SIZE = 22;
|
|
25
|
-
|
|
26
|
-
/// @title A feature implementation of a Zeto fungible token burn contract
|
|
22
|
+
/// @title A feature implementation of a Zeto fungible token burn contract for nullifier-based variants
|
|
27
23
|
/// @author Kaleido, Inc.
|
|
28
|
-
/// @dev
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
/// @dev Mixed-in alongside {ZetoFungibleNullifier} to add a {burn} entry
|
|
25
|
+
/// point that destroys a set of input nullifiers and produces a single
|
|
26
|
+
/// output UTXO holding the remainder. The burn proof attests that the
|
|
27
|
+
/// pre-image UTXOs sum to `output + burn_amount` while preserving
|
|
28
|
+
/// owner-side range and ownership invariants and proving membership
|
|
29
|
+
/// against the historical SMT `root`.
|
|
30
|
+
///
|
|
31
|
+
/// This is the nullifier-flow companion to {ZetoFungibleBurnable}.
|
|
32
|
+
/// Unlike that contract:
|
|
33
|
+
/// - inputs are nullifiers, not UTXOs;
|
|
34
|
+
/// - the SMT `root` is a separate `burn` argument (not encoded in the
|
|
35
|
+
/// proof bytes), so `burn` validates it explicitly;
|
|
36
|
+
/// - the locking lifecycle is unaffected by burning because
|
|
37
|
+
/// {NullifierStorage.validateInputs} (called from {_burn}) only
|
|
38
|
+
/// accepts unspent nullifiers, and locked UTXOs live in a disjoint
|
|
39
|
+
/// part of the ledger.
|
|
40
|
+
abstract contract ZetoFungibleBurnableNullifier is ZetoFungibleNullifier {
|
|
41
|
+
/// @dev Internal-only so it can only be called from a derived
|
|
42
|
+
/// contract's own `initializer`-guarded entrypoint.
|
|
43
|
+
function __ZetoFungibleBurnableNullifier_init(
|
|
44
|
+
IGroth16Verifier burnVerifier,
|
|
45
|
+
IGroth16Verifier batchBurnVerifier
|
|
46
|
+
) internal onlyInitializing {
|
|
47
|
+
ZetoFungibleBurnableNullifierStorage.Layout
|
|
48
|
+
storage $ = ZetoFungibleBurnableNullifierStorage.layout();
|
|
49
|
+
$.burnVerifier = burnVerifier;
|
|
50
|
+
$.batchBurnVerifier = batchBurnVerifier;
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @dev Construct the burn-circuit public-inputs vector. Layout:
|
|
55
|
+
* [nullifiers..., root, enabled-flags..., output]
|
|
56
|
+
* where `enabled-flags[i]` is 1 if `nullifiers[i] != 0` else 0,
|
|
57
|
+
* mirroring the convention used in
|
|
58
|
+
* {Zeto_AnonNullifier.constructPublicInputs}.
|
|
59
|
+
*/
|
|
60
|
+
function constructBurnPublicInputs(
|
|
42
61
|
uint256[] memory nullifiers,
|
|
43
62
|
uint256 output,
|
|
44
63
|
uint256 root
|
|
@@ -46,78 +65,102 @@ abstract contract ZetoFungibleBurnableWithNullifiers is ZetoNullifier {
|
|
|
46
65
|
publicInputs = new uint256[](nullifiers.length * 2 + 2);
|
|
47
66
|
uint256 piIndex = 0;
|
|
48
67
|
|
|
49
|
-
// copy input commitments
|
|
50
68
|
for (uint256 i = 0; i < nullifiers.length; i++) {
|
|
51
69
|
publicInputs[piIndex++] = nullifiers[i];
|
|
52
70
|
}
|
|
53
|
-
|
|
54
|
-
// copy root
|
|
55
71
|
publicInputs[piIndex++] = root;
|
|
56
|
-
|
|
57
|
-
// populate enables
|
|
58
72
|
for (uint256 i = 0; i < nullifiers.length; i++) {
|
|
59
73
|
publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
|
|
60
74
|
}
|
|
61
|
-
|
|
62
75
|
publicInputs[piIndex] = output;
|
|
63
76
|
|
|
64
77
|
return publicInputs;
|
|
65
78
|
}
|
|
66
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @dev Burn a set of nullifier-pre-image UTXOs, leaving a single output
|
|
82
|
+
* UTXO that holds the remainder.
|
|
83
|
+
* @param nullifiers The nullifiers of the input UTXOs being burned.
|
|
84
|
+
* @param output The single output UTXO holding the remainder.
|
|
85
|
+
* @param root The historical SMT root the proof is committed against.
|
|
86
|
+
* Validated against the on-chain root history before state
|
|
87
|
+
* transitions are applied.
|
|
88
|
+
* @param proof The Groth16 proof attesting to value conservation,
|
|
89
|
+
* owner-side range/ownership invariants, and membership of
|
|
90
|
+
* the input UTXOs in the SMT identified by `root`.
|
|
91
|
+
* @param data Opaque data appended to the {UTXOBurn} event for off-chain
|
|
92
|
+
* consumers (e.g. correlation ids).
|
|
93
|
+
*
|
|
94
|
+
* Emits a {UTXOBurn} event.
|
|
95
|
+
*/
|
|
67
96
|
function burn(
|
|
68
|
-
uint256[]
|
|
97
|
+
uint256[] calldata nullifiers,
|
|
69
98
|
uint256 output,
|
|
70
99
|
uint256 root,
|
|
71
100
|
Commonlib.Proof calldata proof,
|
|
72
101
|
bytes calldata data
|
|
73
102
|
) public virtual {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Check the proof
|
|
88
|
-
require(
|
|
89
|
-
_batchBurnVerifier.verifyProof(
|
|
90
|
-
proof.pA,
|
|
91
|
-
proof.pB,
|
|
92
|
-
proof.pC,
|
|
93
|
-
fixedSizeInputs
|
|
94
|
-
),
|
|
95
|
-
"Invalid proof"
|
|
96
|
-
);
|
|
97
|
-
} else {
|
|
98
|
-
// construct the public inputs for verifier
|
|
99
|
-
uint256[] memory publicInputs = constructPublicInputs(
|
|
100
|
-
nullifiers,
|
|
101
|
-
output,
|
|
102
|
-
root
|
|
103
|
-
);
|
|
104
|
-
// construct the public inputs for verifier
|
|
105
|
-
uint256[BURN_INPUT_SIZE] memory fixedSizeInputs;
|
|
106
|
-
for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
|
|
107
|
-
fixedSizeInputs[i] = publicInputs[i];
|
|
108
|
-
}
|
|
109
|
-
// Check the proof
|
|
110
|
-
require(
|
|
111
|
-
_burnVerifier.verifyProof(
|
|
112
|
-
proof.pA,
|
|
113
|
-
proof.pB,
|
|
114
|
-
proof.pC,
|
|
115
|
-
fixedSizeInputs
|
|
116
|
-
),
|
|
117
|
-
"Invalid proof"
|
|
118
|
-
);
|
|
103
|
+
uint256[] memory publicInputs = constructBurnPublicInputs(
|
|
104
|
+
nullifiers,
|
|
105
|
+
output,
|
|
106
|
+
root
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
ZetoFungibleBurnableNullifierStorage.Layout
|
|
110
|
+
storage $ = ZetoFungibleBurnableNullifierStorage.layout();
|
|
111
|
+
IGroth16Verifier verifier = (nullifiers.length > 2)
|
|
112
|
+
? $.batchBurnVerifier
|
|
113
|
+
: $.burnVerifier;
|
|
114
|
+
if (!verifier.verify(proof.pA, proof.pB, proof.pC, publicInputs)) {
|
|
115
|
+
revert InvalidProof();
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
_burn(nullifiers, output, root, data);
|
|
122
119
|
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @dev Validate inputs/outputs/root, then transition state and emit the
|
|
123
|
+
* {UTXOBurn} event. Marked virtual so concrete tokens can wrap
|
|
124
|
+
* with additional bookkeeping if needed.
|
|
125
|
+
*
|
|
126
|
+
* Unlike the historical implementation on `main`, this consumes
|
|
127
|
+
* the nullifiers via {processInputs} and inserts the output UTXO
|
|
128
|
+
* into the SMT via {processOutputs}; without those calls the
|
|
129
|
+
* burned UTXOs would remain spendable and the remainder UTXO
|
|
130
|
+
* would not be a member of the tree.
|
|
131
|
+
*/
|
|
132
|
+
function _burn(
|
|
133
|
+
uint256[] memory nullifiers,
|
|
134
|
+
uint256 output,
|
|
135
|
+
uint256 root,
|
|
136
|
+
bytes calldata data
|
|
137
|
+
) internal virtual {
|
|
138
|
+
validateInputs(nullifiers, false);
|
|
139
|
+
uint256[] memory outputStates = new uint256[](1);
|
|
140
|
+
outputStates[0] = output;
|
|
141
|
+
validateOutputs(outputStates);
|
|
142
|
+
validateRoot(root);
|
|
143
|
+
|
|
144
|
+
processInputs(nullifiers, false);
|
|
145
|
+
processOutputs(outputStates);
|
|
146
|
+
|
|
147
|
+
emit UTXOBurn(nullifiers, output, msg.sender, data);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// @dev ERC-7201 (`erc7201:zeto.storage.ZetoFungibleBurnableNullifier`).
|
|
152
|
+
library ZetoFungibleBurnableNullifierStorage {
|
|
153
|
+
struct Layout {
|
|
154
|
+
IGroth16Verifier burnVerifier;
|
|
155
|
+
IGroth16Verifier batchBurnVerifier;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bytes32 private constant STORAGE_LOCATION =
|
|
159
|
+
0x3ec1ff2ff5e1c50bcb38c7183cc1e67f5f6626ff8f32ea7dbc84147e4b393500;
|
|
160
|
+
|
|
161
|
+
function layout() internal pure returns (Layout storage $) {
|
|
162
|
+
assembly {
|
|
163
|
+
$.slot := STORAGE_LOCATION
|
|
164
|
+
}
|
|
165
|
+
}
|
|
123
166
|
}
|
|
@@ -0,0 +1,167 @@
|
|
|
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 {Commonlib} from "./common/common.sol";
|
|
19
|
+
import {IZeto, MAX_SMT_DEPTH} from "./interfaces/IZeto.sol";
|
|
20
|
+
import {IZetoInitializable} from "./interfaces/IZetoInitializable.sol";
|
|
21
|
+
import {ZetoFungible} from "./zeto_fungible.sol";
|
|
22
|
+
import {IZetoStorage} from "./interfaces/IZetoStorage.sol";
|
|
23
|
+
import {NullifierStorage} from "./storage/nullifier.sol";
|
|
24
|
+
|
|
25
|
+
/// @title A sample base implementation of a Zeto based token contract with nullifiers
|
|
26
|
+
/// @author Kaleido, Inc.
|
|
27
|
+
/// @dev Implements common functionalities of Zeto based tokens using nullifiers
|
|
28
|
+
abstract contract ZetoFungibleNullifier is ZetoFungible {
|
|
29
|
+
function __ZetoFungibleNullifier_init(
|
|
30
|
+
string calldata name_,
|
|
31
|
+
string calldata symbol_,
|
|
32
|
+
address initialOwner,
|
|
33
|
+
IZetoInitializable.VerifiersInfo calldata verifiers
|
|
34
|
+
) internal onlyInitializing {
|
|
35
|
+
IZetoStorage storage_ = new NullifierStorage();
|
|
36
|
+
__ZetoFungible_init(name_, symbol_, initialOwner, verifiers, storage_);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function constructPublicInputsForWithdraw(
|
|
40
|
+
uint256 amount,
|
|
41
|
+
uint256[] memory nullifiers,
|
|
42
|
+
uint256 output,
|
|
43
|
+
bytes memory proof
|
|
44
|
+
) internal override returns (uint256[] memory, Commonlib.Proof memory) {
|
|
45
|
+
// Decode the proof to extract root and proof structure. Root
|
|
46
|
+
// validation is performed here (rather than in a separate
|
|
47
|
+
// pre-decode hop in {validateTransactionProposal}, see L-4) so the
|
|
48
|
+
// proof bytes are decoded exactly once per withdraw call.
|
|
49
|
+
(uint256 root, Commonlib.Proof memory proofStruct) = abi.decode(
|
|
50
|
+
proof,
|
|
51
|
+
(uint256, Commonlib.Proof)
|
|
52
|
+
);
|
|
53
|
+
validateRoot(root);
|
|
54
|
+
|
|
55
|
+
// Calculate the total size needed for public inputs
|
|
56
|
+
uint256 size = _calculateWithdrawPublicInputsSize(nullifiers);
|
|
57
|
+
|
|
58
|
+
// Create and populate the public inputs array
|
|
59
|
+
uint256[] memory publicInputs = new uint256[](size);
|
|
60
|
+
_fillWithdrawPublicInputs(
|
|
61
|
+
publicInputs,
|
|
62
|
+
amount,
|
|
63
|
+
nullifiers,
|
|
64
|
+
root,
|
|
65
|
+
output
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return (publicInputs, proofStruct);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function _calculateWithdrawPublicInputsSize(
|
|
72
|
+
uint256[] memory nullifiers
|
|
73
|
+
) internal pure returns (uint256 size) {
|
|
74
|
+
size = (nullifiers.length * 2) + 3; // nullifiers, enabled flags, amount, root, output
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function _fillWithdrawPublicInputs(
|
|
78
|
+
uint256[] memory publicInputs,
|
|
79
|
+
uint256 amount,
|
|
80
|
+
uint256[] memory nullifiers,
|
|
81
|
+
uint256 root,
|
|
82
|
+
uint256 output
|
|
83
|
+
) internal pure {
|
|
84
|
+
uint256 piIndex = 0;
|
|
85
|
+
|
|
86
|
+
// Copy withdrawal amount
|
|
87
|
+
piIndex = _fillWithdrawAmount(publicInputs, amount, piIndex);
|
|
88
|
+
|
|
89
|
+
// Copy nullifiers
|
|
90
|
+
piIndex = _fillWithdrawNullifiers(publicInputs, nullifiers, piIndex);
|
|
91
|
+
|
|
92
|
+
// Copy root
|
|
93
|
+
piIndex = _fillWithdrawRoot(publicInputs, root, piIndex);
|
|
94
|
+
|
|
95
|
+
// Populate enabled flags
|
|
96
|
+
piIndex = _fillWithdrawEnabledFlags(publicInputs, nullifiers, piIndex);
|
|
97
|
+
|
|
98
|
+
// Copy output commitment
|
|
99
|
+
_fillWithdrawOutput(publicInputs, output, piIndex);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function _fillWithdrawAmount(
|
|
103
|
+
uint256[] memory publicInputs,
|
|
104
|
+
uint256 amount,
|
|
105
|
+
uint256 startIndex
|
|
106
|
+
) internal pure returns (uint256 nextIndex) {
|
|
107
|
+
publicInputs[startIndex] = amount;
|
|
108
|
+
return startIndex + 1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _fillWithdrawNullifiers(
|
|
112
|
+
uint256[] memory publicInputs,
|
|
113
|
+
uint256[] memory nullifiers,
|
|
114
|
+
uint256 startIndex
|
|
115
|
+
) internal pure returns (uint256 nextIndex) {
|
|
116
|
+
uint256 piIndex = startIndex;
|
|
117
|
+
for (uint256 i = 0; i < nullifiers.length; i++) {
|
|
118
|
+
publicInputs[piIndex++] = nullifiers[i];
|
|
119
|
+
}
|
|
120
|
+
return piIndex;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function _fillWithdrawRoot(
|
|
124
|
+
uint256[] memory publicInputs,
|
|
125
|
+
uint256 root,
|
|
126
|
+
uint256 startIndex
|
|
127
|
+
) internal pure returns (uint256 nextIndex) {
|
|
128
|
+
publicInputs[startIndex] = root;
|
|
129
|
+
return startIndex + 1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function _fillWithdrawEnabledFlags(
|
|
133
|
+
uint256[] memory publicInputs,
|
|
134
|
+
uint256[] memory nullifiers,
|
|
135
|
+
uint256 startIndex
|
|
136
|
+
) internal pure returns (uint256 nextIndex) {
|
|
137
|
+
uint256 piIndex = startIndex;
|
|
138
|
+
for (uint256 i = 0; i < nullifiers.length; i++) {
|
|
139
|
+
publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
|
|
140
|
+
}
|
|
141
|
+
return piIndex;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function _fillWithdrawOutput(
|
|
145
|
+
uint256[] memory publicInputs,
|
|
146
|
+
uint256 output,
|
|
147
|
+
uint256 startIndex
|
|
148
|
+
) internal pure {
|
|
149
|
+
publicInputs[startIndex] = output;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// @dev ERC-7201 (`erc7201:zeto.storage.ZetoFungibleNullifier`).
|
|
154
|
+
library ZetoFungibleNullifierStorage {
|
|
155
|
+
struct Layout {
|
|
156
|
+
uint256 __reserved;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
bytes32 private constant STORAGE_LOCATION =
|
|
160
|
+
0xa9ddb64cb7b603a6a83651e5155a95c052516a16afcb7569681d49e92a59ab00;
|
|
161
|
+
|
|
162
|
+
function layout() internal pure returns (Layout storage $) {
|
|
163
|
+
assembly {
|
|
164
|
+
$.slot := STORAGE_LOCATION
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|