@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.0
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 +70 -162
- 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/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 +451 -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 +613 -0
- package/contracts/lib/zeto_non_fungible.sol +236 -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 +9 -3
- package/ignition/modules/lib/deps.ts +8 -0
- package/ignition/modules/zeto_anon_burnable.ts +8 -7
- package/ignition/modules/zeto_anon_enc_nullifier.ts +31 -0
- package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +2 -2
- package/ignition/modules/zeto_anon_nullifier.ts +28 -4
- package/ignition/modules/zeto_anon_nullifier_burnable.ts +50 -16
- package/ignition/modules/zeto_anon_nullifier_kyc.ts +27 -12
- package/ignition/modules/zeto_nf_anon_nullifier.ts +14 -10
- package/package.json +4 -2
- package/scripts/deploy_cloneable.ts +19 -10
- package/scripts/deploy_upgradeable.ts +9 -5
- package/scripts/tokens/Zeto_Anon.ts +3 -3
- package/scripts/tokens/Zeto_AnonBurnable.ts +1 -1
- package/scripts/tokens/Zeto_AnonEnc.ts +12 -3
- package/scripts/tokens/Zeto_AnonEncNullifier.ts +5 -3
- package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +1 -1
- package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifier.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierKyc.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +1 -1
- package/scripts/tokens/Zeto_NfAnon.ts +2 -2
- package/scripts/tokens/Zeto_NfAnonNullifier.ts +1 -1
- package/test/factory.ts +46 -73
- package/test/lib/anon_nullifier_helpers.ts +89 -0
- package/test/lib/anon_zeto_helpers.ts +76 -0
- package/test/lib/deploy.ts +3 -2
- 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 -26
- package/test/utils.ts +144 -21
- package/test/zeto_anon.ts +956 -465
- package/test/zeto_anon_enc.ts +881 -142
- package/test/zeto_anon_enc_nullifier.ts +847 -38
- package/test/zeto_anon_enc_nullifier_kyc.ts +120 -181
- package/test/zeto_anon_enc_nullifier_non_repudiation.ts +77 -46
- package/test/zeto_anon_nullifier.ts +1212 -953
- package/test/zeto_anon_nullifier_kyc.ts +674 -655
- package/test/zeto_anon_nullifier_qurrency.ts +452 -306
- package/test/zeto_nf_anon.ts +737 -137
- package/test/zeto_nf_anon_nullifier.ts +876 -246
- 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,51 +15,39 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
pragma solidity ^0.8.27;
|
|
17
17
|
|
|
18
|
-
import {IZeto} from "./lib/interfaces/
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {Groth16Verifier_WithdrawNullifierBatch} from "./verifiers/verifier_withdraw_nullifier_batch.sol";
|
|
23
|
-
import {Groth16Verifier_AnonNullifierTransfer} from "./verifiers/verifier_anon_nullifier_transfer.sol";
|
|
24
|
-
import {Groth16Verifier_AnonNullifierTransferLocked} from "./verifiers/verifier_anon_nullifier_transferLocked.sol";
|
|
25
|
-
import {Groth16Verifier_AnonNullifierTransferBatch} from "./verifiers/verifier_anon_nullifier_transfer_batch.sol";
|
|
26
|
-
import {Groth16Verifier_AnonNullifierTransferLockedBatch} from "./verifiers/verifier_anon_nullifier_transferLocked_batch.sol";
|
|
27
|
-
import {ZetoNullifier} from "./lib/zeto_nullifier.sol";
|
|
28
|
-
import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol";
|
|
29
|
-
import {Commonlib} from "./lib/common.sol";
|
|
30
|
-
import {IZetoInitializable} from "./lib/interfaces/izeto_initializable.sol";
|
|
18
|
+
import {IZeto, MAX_BATCH} from "./lib/interfaces/IZeto.sol";
|
|
19
|
+
import {ZetoFungibleNullifier} from "./lib/zeto_fungible_nullifier.sol";
|
|
20
|
+
import {Commonlib} from "./lib/common/common.sol";
|
|
21
|
+
import {IZetoInitializable} from "./lib/interfaces/IZetoInitializable.sol";
|
|
31
22
|
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
32
|
-
import {console} from "hardhat/console.sol";
|
|
33
|
-
|
|
34
|
-
uint256 constant INPUT_SIZE = 7;
|
|
35
|
-
uint256 constant INPUT_SIZE_LOCKED = 8;
|
|
36
|
-
uint256 constant BATCH_INPUT_SIZE = 31;
|
|
37
|
-
uint256 constant BATCH_INPUT_SIZE_LOCKED = 32;
|
|
38
23
|
|
|
39
24
|
/// @title A sample implementation of a Zeto based fungible token with anonymity and history masking
|
|
40
25
|
/// @author Kaleido, Inc.
|
|
26
|
+
/// @notice Decimals: this token uses **4** decimals, inherited from
|
|
27
|
+
/// {ZetoCommon.decimals}. Indexers and UIs reading this contract
|
|
28
|
+
/// directly should treat balances accordingly.
|
|
41
29
|
/// @dev The proof has the following statements:
|
|
42
30
|
/// - each value in the output commitments must be a positive number in the range 0 ~ (2\*\*40 - 1)
|
|
43
31
|
/// - the sum of the nullified values match the sum of output values
|
|
44
32
|
/// - the hashes in the input and output match the hash(value, salt, owner public key) formula
|
|
45
33
|
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes, which match the corresponding nullifiers
|
|
46
34
|
/// - the nullifiers represent input commitments that are included in a Sparse Merkle Tree represented by the root hash
|
|
47
|
-
contract Zeto_AnonNullifier is
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
35
|
+
contract Zeto_AnonNullifier is ZetoFungibleNullifier, UUPSUpgradeable {
|
|
36
|
+
/// @dev Lock the implementation contract on construction so that
|
|
37
|
+
/// {initialize} can only ever run on a proxy. Without this,
|
|
38
|
+
/// anyone could call {initialize} directly on the deployed
|
|
39
|
+
/// implementation, become its owner, and then `upgradeTo(any)`
|
|
40
|
+
/// via {_authorizeUpgrade} (the OZ "implementation takeover"
|
|
41
|
+
/// pattern, CVE-2022-35961 family). See OpenZeppelin's
|
|
42
|
+
/// `Initializable._disableInitializers` for the rationale.
|
|
43
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
44
|
+
constructor() {
|
|
45
|
+
_disableInitializers();
|
|
46
|
+
}
|
|
59
47
|
|
|
60
48
|
function initialize(
|
|
61
|
-
string
|
|
62
|
-
string
|
|
49
|
+
string calldata name,
|
|
50
|
+
string calldata symbol,
|
|
63
51
|
address initialOwner,
|
|
64
52
|
IZetoInitializable.VerifiersInfo calldata verifiers
|
|
65
53
|
) public virtual initializer {
|
|
@@ -67,29 +55,12 @@ contract Zeto_AnonNullifier is
|
|
|
67
55
|
}
|
|
68
56
|
|
|
69
57
|
function __ZetoAnonNullifier_init(
|
|
70
|
-
string
|
|
71
|
-
string
|
|
58
|
+
string calldata name_,
|
|
59
|
+
string calldata symbol_,
|
|
72
60
|
address initialOwner,
|
|
73
61
|
IZetoInitializable.VerifiersInfo calldata verifiers
|
|
74
62
|
) internal onlyInitializing {
|
|
75
|
-
|
|
76
|
-
__ZetoFungibleWithdrawWithNullifiers_init(
|
|
77
|
-
(Groth16Verifier_Deposit)(verifiers.depositVerifier),
|
|
78
|
-
(Groth16Verifier_WithdrawNullifier)(verifiers.withdrawVerifier),
|
|
79
|
-
(Groth16Verifier_WithdrawNullifierBatch)(
|
|
80
|
-
verifiers.batchWithdrawVerifier
|
|
81
|
-
)
|
|
82
|
-
);
|
|
83
|
-
_verifier = (Groth16Verifier_AnonNullifierTransfer)(verifiers.verifier);
|
|
84
|
-
_lockVerifier = (Groth16Verifier_AnonNullifierTransferLocked)(
|
|
85
|
-
verifiers.lockVerifier
|
|
86
|
-
);
|
|
87
|
-
_batchVerifier = (Groth16Verifier_AnonNullifierTransferBatch)(
|
|
88
|
-
verifiers.batchVerifier
|
|
89
|
-
);
|
|
90
|
-
_batchLockVerifier = (Groth16Verifier_AnonNullifierTransferLockedBatch)(
|
|
91
|
-
verifiers.batchLockVerifier
|
|
92
|
-
);
|
|
63
|
+
__ZetoFungibleNullifier_init(name_, symbol_, initialOwner, verifiers);
|
|
93
64
|
}
|
|
94
65
|
|
|
95
66
|
function _authorizeUpgrade(address) internal override onlyOwner {}
|
|
@@ -97,284 +68,179 @@ contract Zeto_AnonNullifier is
|
|
|
97
68
|
function constructPublicInputs(
|
|
98
69
|
uint256[] memory nullifiers,
|
|
99
70
|
uint256[] memory outputs,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
71
|
+
bytes memory proof,
|
|
72
|
+
bool inputsLocked
|
|
73
|
+
)
|
|
74
|
+
internal
|
|
75
|
+
virtual
|
|
76
|
+
override
|
|
77
|
+
returns (uint256[] memory, Commonlib.Proof memory)
|
|
78
|
+
{
|
|
79
|
+
// Decode the proof to extract root and proof structure. Done once
|
|
80
|
+
// here so that {validateTransactionProposal} below can skip the
|
|
81
|
+
// root-only pre-decode it used to perform; root validation happens
|
|
82
|
+
// here instead.
|
|
83
|
+
uint256 root;
|
|
84
|
+
Commonlib.Proof memory proofStruct;
|
|
85
|
+
if (!inputsLocked) {
|
|
86
|
+
(root, proofStruct) = abi.decode(proof, (uint256, Commonlib.Proof));
|
|
87
|
+
validateRoot(root);
|
|
88
|
+
} else {
|
|
89
|
+
proofStruct = abi.decode(proof, (Commonlib.Proof));
|
|
114
90
|
}
|
|
115
|
-
// copy root
|
|
116
|
-
publicInputs[piIndex++] = root;
|
|
117
91
|
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
|
|
121
|
-
}
|
|
92
|
+
// Get extra inputs from derived contracts
|
|
93
|
+
uint256[] memory extra = extraInputs();
|
|
122
94
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
95
|
+
// Calculate the total size needed for public inputs
|
|
96
|
+
uint256 size = _calculatePublicInputsSize(
|
|
97
|
+
nullifiers,
|
|
98
|
+
outputs,
|
|
99
|
+
extra,
|
|
100
|
+
inputsLocked
|
|
101
|
+
);
|
|
127
102
|
|
|
128
|
-
|
|
103
|
+
// Create and populate the public inputs array
|
|
104
|
+
uint256[] memory publicInputs = new uint256[](size);
|
|
105
|
+
_fillPublicInputs(
|
|
106
|
+
publicInputs,
|
|
107
|
+
nullifiers,
|
|
108
|
+
outputs,
|
|
109
|
+
extra,
|
|
110
|
+
root,
|
|
111
|
+
inputsLocked
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return (publicInputs, proofStruct);
|
|
129
115
|
}
|
|
130
116
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
*
|
|
134
|
-
* @param nullifiers Array of nullifiers that are secretly bound to UTXOs to be spent by the transaction.
|
|
135
|
-
* @param outputs Array of new UTXOs to generate, for future transactions to spend.
|
|
136
|
-
* @param root The root hash of the Sparse Merkle Tree that contains the nullifiers.
|
|
137
|
-
* @param proof A zero knowledge proof that the submitter is authorized to spend the inputs, and
|
|
138
|
-
* that the outputs are valid in terms of obeying mass conservation rules.
|
|
139
|
-
*
|
|
140
|
-
* Emits a {UTXOTransfer} event.
|
|
141
|
-
*/
|
|
142
|
-
function transfer(
|
|
143
|
-
uint256[] memory nullifiers,
|
|
117
|
+
function _calculatePublicInputsSize(
|
|
118
|
+
uint256[] memory inputs,
|
|
144
119
|
uint256[] memory outputs,
|
|
145
|
-
uint256
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
outputArray[i] = outputs[i];
|
|
120
|
+
uint256[] memory extra,
|
|
121
|
+
bool inputsLocked
|
|
122
|
+
) internal pure returns (uint256 size) {
|
|
123
|
+
if (inputsLocked) {
|
|
124
|
+
// locked inputs are UTXOs not nullifiers
|
|
125
|
+
size =
|
|
126
|
+
inputs.length +
|
|
127
|
+
extra.length + // extra inputs
|
|
128
|
+
outputs.length; // output commitments
|
|
129
|
+
} else {
|
|
130
|
+
size =
|
|
131
|
+
(inputs.length * 2) + // nullifiers and enabled flags
|
|
132
|
+
1 + // root
|
|
133
|
+
extra.length + // extra inputs
|
|
134
|
+
outputs.length; // output commitments
|
|
161
135
|
}
|
|
162
|
-
emit UTXOTransfer(nullifierArray, outputArray, msg.sender, data);
|
|
163
|
-
return true;
|
|
164
136
|
}
|
|
165
137
|
|
|
166
|
-
function
|
|
167
|
-
uint256[] memory
|
|
138
|
+
function _fillPublicInputs(
|
|
139
|
+
uint256[] memory publicInputs,
|
|
140
|
+
uint256[] memory inputs,
|
|
168
141
|
uint256[] memory outputs,
|
|
142
|
+
uint256[] memory extra,
|
|
169
143
|
uint256 root,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
uint256[] memory empty;
|
|
178
|
-
processInputsAndOutputs(nullifiers, outputs, empty, address(0));
|
|
144
|
+
bool inputsLocked
|
|
145
|
+
) internal view {
|
|
146
|
+
uint256 piIndex = 0;
|
|
147
|
+
|
|
148
|
+
if (!inputsLocked) {
|
|
149
|
+
// Copy nullifiers
|
|
150
|
+
piIndex = _fillInputs_Nullifier(publicInputs, inputs, piIndex);
|
|
179
151
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
152
|
+
// Copy root
|
|
153
|
+
publicInputs[piIndex++] = root;
|
|
154
|
+
|
|
155
|
+
// Populate enabled flags
|
|
156
|
+
piIndex = _fillEnabledFlags_Nullifier(
|
|
157
|
+
publicInputs,
|
|
158
|
+
inputs,
|
|
159
|
+
piIndex
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Copy extra inputs
|
|
163
|
+
piIndex = _fillExtraInputs_Nullifier(publicInputs, extra, piIndex);
|
|
164
|
+
|
|
165
|
+
// Copy output commitments
|
|
166
|
+
_fillOutputCommitments_Nullifier(publicInputs, outputs, piIndex);
|
|
167
|
+
} else {
|
|
168
|
+
// Copy inputs
|
|
169
|
+
piIndex = _fillInputs_Nullifier(publicInputs, inputs, piIndex);
|
|
170
|
+
|
|
171
|
+
// Copy extra inputs
|
|
172
|
+
piIndex = _fillExtraInputs_Nullifier(publicInputs, extra, piIndex);
|
|
173
|
+
|
|
174
|
+
// Copy output commitments
|
|
175
|
+
_fillOutputCommitments_Nullifier(publicInputs, outputs, piIndex);
|
|
185
176
|
}
|
|
186
|
-
emit UTXOTransfer(nullifierArray, outputArray, msg.sender, data);
|
|
187
|
-
return true;
|
|
188
177
|
}
|
|
189
178
|
|
|
190
|
-
function
|
|
191
|
-
uint256
|
|
192
|
-
uint256[] memory
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
179
|
+
function _fillInputs_Nullifier(
|
|
180
|
+
uint256[] memory publicInputs,
|
|
181
|
+
uint256[] memory inputs,
|
|
182
|
+
uint256 startIndex
|
|
183
|
+
) internal pure returns (uint256 nextIndex) {
|
|
184
|
+
uint256 piIndex = startIndex;
|
|
185
|
+
for (uint256 i = 0; i < inputs.length; i++) {
|
|
186
|
+
publicInputs[piIndex++] = inputs[i];
|
|
187
|
+
}
|
|
188
|
+
return piIndex;
|
|
198
189
|
}
|
|
199
190
|
|
|
200
|
-
function
|
|
201
|
-
uint256
|
|
191
|
+
function _fillEnabledFlags_Nullifier(
|
|
192
|
+
uint256[] memory publicInputs,
|
|
202
193
|
uint256[] memory nullifiers,
|
|
203
|
-
uint256
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
// Check and pad inputs and outputs based on the max size
|
|
211
|
-
nullifiers = checkAndPadCommitments(nullifiers);
|
|
212
|
-
outputs = checkAndPadCommitments(outputs);
|
|
213
|
-
validateTransactionProposal(nullifiers, outputs, root, false);
|
|
214
|
-
_withdrawWithNullifiers(amount, nullifiers, output, root, proof);
|
|
215
|
-
uint256[] memory empty;
|
|
216
|
-
processInputsAndOutputs(nullifiers, outputs, empty, address(0));
|
|
217
|
-
emit UTXOWithdraw(amount, nullifiers, output, msg.sender, data);
|
|
194
|
+
uint256 startIndex
|
|
195
|
+
) internal pure returns (uint256 nextIndex) {
|
|
196
|
+
uint256 piIndex = startIndex;
|
|
197
|
+
for (uint256 i = 0; i < nullifiers.length; i++) {
|
|
198
|
+
publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1;
|
|
199
|
+
}
|
|
200
|
+
return piIndex;
|
|
218
201
|
}
|
|
219
202
|
|
|
220
|
-
function
|
|
221
|
-
uint256[] memory
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
203
|
+
function _fillExtraInputs_Nullifier(
|
|
204
|
+
uint256[] memory publicInputs,
|
|
205
|
+
uint256[] memory extra,
|
|
206
|
+
uint256 startIndex
|
|
207
|
+
) internal pure returns (uint256 nextIndex) {
|
|
208
|
+
uint256 piIndex = startIndex;
|
|
209
|
+
for (uint256 i = 0; i < extra.length; i++) {
|
|
210
|
+
publicInputs[piIndex++] = extra[i];
|
|
211
|
+
}
|
|
212
|
+
return piIndex;
|
|
225
213
|
}
|
|
226
214
|
|
|
227
|
-
function
|
|
228
|
-
uint256[] memory
|
|
215
|
+
function _fillOutputCommitments_Nullifier(
|
|
216
|
+
uint256[] memory publicInputs,
|
|
229
217
|
uint256[] memory outputs,
|
|
230
|
-
uint256
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
address delegate,
|
|
234
|
-
bytes calldata data
|
|
235
|
-
) public {
|
|
236
|
-
// merge the outputs and lockedOutputs and do a regular transfer
|
|
237
|
-
uint256[] memory allOutputs = new uint256[](
|
|
238
|
-
outputs.length + lockedOutputs.length
|
|
239
|
-
);
|
|
218
|
+
uint256 startIndex
|
|
219
|
+
) internal pure {
|
|
220
|
+
uint256 piIndex = startIndex;
|
|
240
221
|
for (uint256 i = 0; i < outputs.length; i++) {
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
for (uint256 i = 0; i < lockedOutputs.length; i++) {
|
|
244
|
-
allOutputs[outputs.length + i] = lockedOutputs[i];
|
|
222
|
+
publicInputs[piIndex++] = outputs[i];
|
|
245
223
|
}
|
|
246
|
-
nullifiers = checkAndPadCommitments(nullifiers);
|
|
247
|
-
allOutputs = checkAndPadCommitments(allOutputs);
|
|
248
|
-
validateTransactionProposal(nullifiers, allOutputs, root, false);
|
|
249
|
-
verifyProof(nullifiers, allOutputs, root, proof);
|
|
250
|
-
|
|
251
|
-
processNullifiers(nullifiers);
|
|
252
|
-
|
|
253
|
-
// lock the intended outputs
|
|
254
|
-
_lock(nullifiers, outputs, lockedOutputs, delegate, data);
|
|
255
224
|
}
|
|
256
225
|
|
|
257
|
-
function
|
|
258
|
-
|
|
259
|
-
uint256[]
|
|
260
|
-
uint256 root,
|
|
261
|
-
Commonlib.Proof calldata proof,
|
|
262
|
-
bytes calldata data
|
|
263
|
-
) public {
|
|
264
|
-
transferLocked(nullifiers, outputs, root, proof, data);
|
|
226
|
+
function extraInputs() internal view virtual returns (uint256[] memory) {
|
|
227
|
+
// no extra inputs for this contract
|
|
228
|
+
return new uint256[](0);
|
|
265
229
|
}
|
|
230
|
+
}
|
|
266
231
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
uint256
|
|
271
|
-
Commonlib.Proof calldata proof
|
|
272
|
-
) public view returns (bool) {
|
|
273
|
-
if (nullifiers.length > 2 || outputs.length > 2) {
|
|
274
|
-
uint256[] memory publicInputs = constructPublicInputs(
|
|
275
|
-
nullifiers,
|
|
276
|
-
outputs,
|
|
277
|
-
root,
|
|
278
|
-
BATCH_INPUT_SIZE,
|
|
279
|
-
false
|
|
280
|
-
);
|
|
281
|
-
// construct the public inputs for batchVerifier
|
|
282
|
-
uint256[BATCH_INPUT_SIZE] memory fixedSizeInputs;
|
|
283
|
-
for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
|
|
284
|
-
fixedSizeInputs[i] = publicInputs[i];
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Check the proof using batchVerifier
|
|
288
|
-
require(
|
|
289
|
-
_batchVerifier.verifyProof(
|
|
290
|
-
proof.pA,
|
|
291
|
-
proof.pB,
|
|
292
|
-
proof.pC,
|
|
293
|
-
fixedSizeInputs
|
|
294
|
-
),
|
|
295
|
-
"Invalid proof (batch)"
|
|
296
|
-
);
|
|
297
|
-
} else {
|
|
298
|
-
uint256[] memory publicInputs = constructPublicInputs(
|
|
299
|
-
nullifiers,
|
|
300
|
-
outputs,
|
|
301
|
-
root,
|
|
302
|
-
INPUT_SIZE,
|
|
303
|
-
false
|
|
304
|
-
);
|
|
305
|
-
// construct the public inputs for verifier
|
|
306
|
-
uint256[INPUT_SIZE] memory fixedSizeInputs;
|
|
307
|
-
for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
|
|
308
|
-
fixedSizeInputs[i] = publicInputs[i];
|
|
309
|
-
}
|
|
310
|
-
// Check the proof
|
|
311
|
-
require(
|
|
312
|
-
_verifier.verifyProof(
|
|
313
|
-
proof.pA,
|
|
314
|
-
proof.pB,
|
|
315
|
-
proof.pC,
|
|
316
|
-
fixedSizeInputs
|
|
317
|
-
),
|
|
318
|
-
"Invalid proof"
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
return true;
|
|
232
|
+
/// @dev ERC-7201 (`erc7201:zeto.storage.Zeto_AnonNullifier`).
|
|
233
|
+
library Zeto_AnonNullifierStorage {
|
|
234
|
+
struct Layout {
|
|
235
|
+
uint256 __reserved;
|
|
322
236
|
}
|
|
323
237
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
uint256[] memory outputs,
|
|
327
|
-
uint256 root,
|
|
328
|
-
Commonlib.Proof calldata proof
|
|
329
|
-
) public view returns (bool) {
|
|
330
|
-
if (nullifiers.length > 2 || outputs.length > 2) {
|
|
331
|
-
uint256[] memory publicInputs = constructPublicInputs(
|
|
332
|
-
nullifiers,
|
|
333
|
-
outputs,
|
|
334
|
-
root,
|
|
335
|
-
BATCH_INPUT_SIZE_LOCKED,
|
|
336
|
-
true
|
|
337
|
-
);
|
|
338
|
-
// construct the public inputs for batchVerifier
|
|
339
|
-
uint256[BATCH_INPUT_SIZE_LOCKED] memory fixedSizeInputs;
|
|
340
|
-
for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
|
|
341
|
-
fixedSizeInputs[i] = publicInputs[i];
|
|
342
|
-
}
|
|
238
|
+
bytes32 private constant STORAGE_LOCATION =
|
|
239
|
+
0xe49aec919d5bc8263575d088c75c14f60ed5ec12d5e1b7a7a34166fca4de8b00;
|
|
343
240
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
proof.pA,
|
|
348
|
-
proof.pB,
|
|
349
|
-
proof.pC,
|
|
350
|
-
fixedSizeInputs
|
|
351
|
-
),
|
|
352
|
-
"Invalid proof (batch)"
|
|
353
|
-
);
|
|
354
|
-
} else {
|
|
355
|
-
uint256[] memory publicInputs = constructPublicInputs(
|
|
356
|
-
nullifiers,
|
|
357
|
-
outputs,
|
|
358
|
-
root,
|
|
359
|
-
INPUT_SIZE_LOCKED,
|
|
360
|
-
true
|
|
361
|
-
);
|
|
362
|
-
// construct the public inputs for verifier
|
|
363
|
-
uint256[INPUT_SIZE_LOCKED] memory fixedSizeInputs;
|
|
364
|
-
for (uint256 i = 0; i < fixedSizeInputs.length; i++) {
|
|
365
|
-
fixedSizeInputs[i] = publicInputs[i];
|
|
366
|
-
}
|
|
367
|
-
// Check the proof
|
|
368
|
-
require(
|
|
369
|
-
_lockVerifier.verifyProof(
|
|
370
|
-
proof.pA,
|
|
371
|
-
proof.pB,
|
|
372
|
-
proof.pC,
|
|
373
|
-
fixedSizeInputs
|
|
374
|
-
),
|
|
375
|
-
"Invalid proof"
|
|
376
|
-
);
|
|
241
|
+
function layout() internal pure returns (Layout storage $) {
|
|
242
|
+
assembly {
|
|
243
|
+
$.slot := STORAGE_LOCATION
|
|
377
244
|
}
|
|
378
|
-
return true;
|
|
379
245
|
}
|
|
380
246
|
}
|
|
@@ -15,35 +15,85 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
pragma solidity ^0.8.27;
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
import {Groth16Verifier_BurnNullifierBatch} from "./verifiers/verifier_burn_nullifier_batch.sol";
|
|
18
|
+
import {IZetoInitializable} from "./lib/interfaces/IZetoInitializable.sol";
|
|
20
19
|
import {Zeto_AnonNullifier} from "./zeto_anon_nullifier.sol";
|
|
21
|
-
import {
|
|
20
|
+
import {ZetoFungibleBurnableNullifier} from "./lib/zeto_fungible_burn_nullifier.sol";
|
|
21
|
+
import {Commonlib} from "./lib/common/common.sol";
|
|
22
|
+
import {ZetoCommon} from "./lib/zeto_common.sol";
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/// @title A sample implementation of a Zeto based fungible token with anonymity and no encryption
|
|
24
|
+
/// @title A sample implementation of a Zeto based fungible token with
|
|
25
|
+
/// anonymity, history masking via nullifiers, and {burn} support.
|
|
27
26
|
/// @author Kaleido, Inc.
|
|
28
|
-
/// @
|
|
27
|
+
/// @notice Decimals: this token uses **4** decimals, inherited from
|
|
28
|
+
/// {ZetoCommon.decimals}. Indexers and UIs reading this contract
|
|
29
|
+
/// directly should treat balances accordingly.
|
|
30
|
+
/// @dev The transfer proof has the following statements:
|
|
29
31
|
/// - each value in the output commitments must be a positive number in the range 0 ~ (2\*\*40 - 1)
|
|
30
|
-
/// - the sum of the
|
|
31
|
-
/// - the hashes in the input and output match the
|
|
32
|
-
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes
|
|
32
|
+
/// - the sum of the nullified values match the sum of output values
|
|
33
|
+
/// - the hashes in the input and output match the hash(value, salt, owner public key) formula
|
|
34
|
+
/// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes, which match the corresponding nullifiers
|
|
35
|
+
/// - the nullifiers represent input commitments that are included in a Sparse Merkle Tree represented by the root hash
|
|
36
|
+
///
|
|
37
|
+
/// The burn proof has the analogous statements with the output side
|
|
38
|
+
/// collapsed to a single remainder commitment.
|
|
39
|
+
///
|
|
40
|
+
/// Composes {Zeto_AnonNullifier} (transfer + lock lifecycle) with
|
|
41
|
+
/// {ZetoFungibleBurnableNullifier} (burn entry point). Both base
|
|
42
|
+
/// paths converge on the abstract {ZetoCommon.constructPublicInputs}
|
|
43
|
+
/// hook, so this leaf contract must explicitly disambiguate the
|
|
44
|
+
/// override; it simply forwards to {Zeto_AnonNullifier}'s
|
|
45
|
+
/// implementation, which is the same proof layout used for both
|
|
46
|
+
/// unlocked transfers and the locked-input spend flow inherited from
|
|
47
|
+
/// {ZetoFungible}.
|
|
48
|
+
///
|
|
49
|
+
/// Unlike the pre-{ILockableCapability} version, there is no longer a
|
|
50
|
+
/// separate `constructPublicInputsForLock` hook to override; the lock
|
|
51
|
+
/// lifecycle now reuses {constructPublicInputs} with `inputsLocked = true`.
|
|
33
52
|
contract Zeto_AnonNullifierBurnable is
|
|
34
53
|
Zeto_AnonNullifier,
|
|
35
|
-
|
|
54
|
+
ZetoFungibleBurnableNullifier
|
|
36
55
|
{
|
|
56
|
+
/// @dev Lock the implementation contract on construction. The parent
|
|
57
|
+
/// {Zeto_AnonNullifier} already does this via its own constructor
|
|
58
|
+
/// (which Solidity invokes as part of every leaf's deployment),
|
|
59
|
+
/// but we restate it here so the H-2 protection survives any
|
|
60
|
+
/// future refactor that changes the inheritance graph.
|
|
61
|
+
/// `_disableInitializers()` is idempotent, so the duplicate call
|
|
62
|
+
/// is a harmless no-op.
|
|
63
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
64
|
+
constructor() {
|
|
65
|
+
_disableInitializers();
|
|
66
|
+
}
|
|
67
|
+
|
|
37
68
|
function initialize(
|
|
38
|
-
string
|
|
39
|
-
string
|
|
69
|
+
string calldata name,
|
|
70
|
+
string calldata symbol,
|
|
40
71
|
address initialOwner,
|
|
41
|
-
VerifiersInfo calldata verifiers
|
|
72
|
+
IZetoInitializable.VerifiersInfo calldata verifiers
|
|
42
73
|
) public override initializer {
|
|
43
74
|
__ZetoAnonNullifier_init(name, symbol, initialOwner, verifiers);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
75
|
+
__ZetoFungibleBurnableNullifier_init(
|
|
76
|
+
verifiers.burnVerifier,
|
|
77
|
+
verifiers.batchBurnVerifier
|
|
47
78
|
);
|
|
48
79
|
}
|
|
80
|
+
|
|
81
|
+
function constructPublicInputs(
|
|
82
|
+
uint256[] memory inputs,
|
|
83
|
+
uint256[] memory outputs,
|
|
84
|
+
bytes memory proof,
|
|
85
|
+
bool inputsLocked
|
|
86
|
+
)
|
|
87
|
+
internal
|
|
88
|
+
override(Zeto_AnonNullifier, ZetoCommon)
|
|
89
|
+
returns (uint256[] memory, Commonlib.Proof memory)
|
|
90
|
+
{
|
|
91
|
+
return
|
|
92
|
+
Zeto_AnonNullifier.constructPublicInputs(
|
|
93
|
+
inputs,
|
|
94
|
+
outputs,
|
|
95
|
+
proof,
|
|
96
|
+
inputsLocked
|
|
97
|
+
);
|
|
98
|
+
}
|
|
49
99
|
}
|