@@ -32,6 +32,11 @@ class SpotTradeCircuit : public BaseTransactionCircuit
32
32
DynamicBalanceGadget balanceA_O;
33
33
DynamicBalanceGadget balanceB_O;
34
34
35
+ DynamicBalanceGadget vbalanceS_A;
36
+ DynamicBalanceGadget vbalanceB_A;
37
+ DynamicBalanceGadget vbalanceS_B;
38
+ DynamicBalanceGadget vbalanceB_B;
39
+
35
40
// Order fills
36
41
FloatGadget fillS_A;
37
42
FloatGadget fillS_B;
@@ -59,6 +64,16 @@ class SpotTradeCircuit : public BaseTransactionCircuit
59
64
TransferGadget protocolFeeA_from_balanceAO_to_balanceAP;
60
65
TransferGadget protocolFeeB_from_balanceBO_to_balanceBP;
61
66
67
+ /* Virtual Token Transfers */
68
+ TernaryGadget vfills_S_A;
69
+ TernaryGadget vfills_B_A;
70
+ TernaryGadget vfills_S_B;
71
+ TernaryGadget vfills_B_B;
72
+ SubGadget update_vbalanceS_A;
73
+ AddGadget update_vbalanceB_A;
74
+ SubGadget update_vbalanceS_B;
75
+ AddGadget update_vbalanceB_B;
76
+
62
77
// AMM validation
63
78
ValidateAMMGadget validateAMM;
64
79
@@ -82,6 +97,12 @@ class SpotTradeCircuit : public BaseTransactionCircuit
82
97
balanceA_O(pb, state.oper.balanceA, FMT(prefix, " .balanceA_O" )),
83
98
balanceB_O(pb, state.oper.balanceB, FMT(prefix, " .balanceB_O" )),
84
99
100
+ // Virtual balances
101
+ vbalanceS_A(pb, state.accountA.balanceS.weightAMM, FMT(prefix, " .vbalanceS_A" )),
102
+ vbalanceB_A(pb, state.accountA.balanceB.weightAMM, FMT(prefix, " .vbalanceB_A" )),
103
+ vbalanceS_B(pb, state.accountB.balanceS.weightAMM, FMT(prefix, " .vbalanceS_B" )),
104
+ vbalanceB_B(pb, state.accountB.balanceB.weightAMM, FMT(prefix, " .vbalanceB_B" )),
105
+
85
106
// Order fills
86
107
fillS_A(pb, state.constants, Float24Encoding, FMT(prefix, " .fillS_A" )),
87
108
fillS_B(pb, state.constants, Float24Encoding, FMT(prefix, " .fillS_B" )),
@@ -175,28 +196,55 @@ class SpotTradeCircuit : public BaseTransactionCircuit
175
196
feeCalculatorB.getProtocolFee(),
176
197
FMT(prefix, " .protocolFeeB_from_balanceBO_to_balanceBP" )),
177
198
199
+ /* Virtual balance updates (for AMMs only) */
200
+ vfills_S_A(pb, orderA.amm.packed, fillS_A.value(), state.constants._0, FMT(prefix, " .vfills_S_A" )),
201
+ vfills_B_A(pb, orderA.amm.packed, fillS_B.value(), state.constants._0, FMT(prefix, " .vfills_B_A" )),
202
+ vfills_S_B(pb, orderB.amm.packed, fillS_B.value(), state.constants._0, FMT(prefix, " .vfills_S_B" )),
203
+ vfills_B_B(pb, orderB.amm.packed, fillS_A.value(), state.constants._0, FMT(prefix, " .vfills_B_B" )),
204
+ update_vbalanceS_A(
205
+ pb,
206
+ state.accountA.balanceS.weightAMM,
207
+ vfills_S_A.result(),
208
+ NUM_BITS_AMOUNT,
209
+ FMT(prefix, " .update_vbalanceS_A" )),
210
+ update_vbalanceB_A(
211
+ pb,
212
+ state.accountA.balanceB.weightAMM,
213
+ vfills_B_A.result(),
214
+ NUM_BITS_AMOUNT,
215
+ FMT(prefix, " .update_vbalanceB_A" )),
216
+ update_vbalanceS_B(
217
+ pb,
218
+ state.accountB.balanceS.weightAMM,
219
+ vfills_S_B.result(),
220
+ NUM_BITS_AMOUNT,
221
+ FMT(prefix, " .update_vbalanceS_B" )),
222
+ update_vbalanceB_B(
223
+ pb,
224
+ state.accountB.balanceB.weightAMM,
225
+ vfills_B_B.result(),
226
+ NUM_BITS_AMOUNT,
227
+ FMT(prefix, " .update_vbalanceB_B" )),
228
+
178
229
validateAMM(
179
230
pb,
180
231
state.constants,
232
+ isSpotTradeTx.result(),
181
233
{orderA.amm .packed ,
182
234
orderA.feeBips .packed ,
183
235
fillS_A.value (),
184
- state.accountA .balanceS .balance ,
185
- state.accountA .balanceB .balance ,
186
- balanceS_A.balance (),
187
- balanceB_A.balance (),
188
236
state.accountA .balanceS .weightAMM ,
189
237
state.accountA .balanceB .weightAMM ,
238
+ update_vbalanceS_A.result (),
239
+ update_vbalanceB_A.result (),
190
240
state.accountA .account .feeBipsAMM },
191
241
{orderB.amm .packed ,
192
242
orderB.feeBips .packed ,
193
243
fillS_B.value (),
194
- state.accountB .balanceS .balance ,
195
- state.accountB .balanceB .balance ,
196
- balanceS_B.balance (),
197
- balanceB_B.balance (),
198
244
state.accountB .balanceS .weightAMM ,
199
245
state.accountB .balanceB .weightAMM ,
246
+ update_vbalanceS_B.result (),
247
+ update_vbalanceB_B.result (),
200
248
state.accountB .account .feeBipsAMM },
201
249
FMT (prefix, " .validateAMM" ))
202
250
{
@@ -210,6 +258,8 @@ class SpotTradeCircuit : public BaseTransactionCircuit
210
258
setOutput (TXV_STORAGE_A_STORAGEID, orderA.storageID .packed );
211
259
setOutput (TXV_BALANCE_A_S_BALANCE, balanceS_A.balance ());
212
260
setOutput (TXV_BALANCE_A_B_BALANCE, balanceB_A.balance ());
261
+ setOutput (TXV_BALANCE_A_S_WEIGHTAMM, update_vbalanceS_A.result ());
262
+ setOutput (TXV_BALANCE_A_B_WEIGHTAMM, update_vbalanceB_A.result ());
213
263
setArrayOutput (TXV_ACCOUNT_A_ADDRESS, orderA.accountID .bits );
214
264
215
265
// Update account B
@@ -218,6 +268,8 @@ class SpotTradeCircuit : public BaseTransactionCircuit
218
268
setOutput (TXV_STORAGE_B_STORAGEID, orderB.storageID .packed );
219
269
setOutput (TXV_BALANCE_B_S_BALANCE, balanceS_B.balance ());
220
270
setOutput (TXV_BALANCE_B_B_BALANCE, balanceB_B.balance ());
271
+ setOutput (TXV_BALANCE_B_S_WEIGHTAMM, update_vbalanceS_B.result ());
272
+ setOutput (TXV_BALANCE_B_B_WEIGHTAMM, update_vbalanceB_B.result ());
221
273
setArrayOutput (TXV_ACCOUNT_B_ADDRESS, orderB.accountID .bits );
222
274
223
275
// Update balances of the protocol fee pool
@@ -252,6 +304,12 @@ class SpotTradeCircuit : public BaseTransactionCircuit
252
304
balanceA_O.generate_r1cs_witness ();
253
305
balanceB_O.generate_r1cs_witness ();
254
306
307
+ // Virtual balances
308
+ vbalanceS_A.generate_r1cs_witness ();
309
+ vbalanceB_A.generate_r1cs_witness ();
310
+ vbalanceS_B.generate_r1cs_witness ();
311
+ vbalanceB_B.generate_r1cs_witness ();
312
+
255
313
// Order fills
256
314
fillS_A.generate_r1cs_witness (spotTrade.fillS_A );
257
315
fillS_B.generate_r1cs_witness (spotTrade.fillS_B );
@@ -279,6 +337,16 @@ class SpotTradeCircuit : public BaseTransactionCircuit
279
337
protocolFeeA_from_balanceAO_to_balanceAP.generate_r1cs_witness ();
280
338
protocolFeeB_from_balanceBO_to_balanceBP.generate_r1cs_witness ();
281
339
340
+ /* Virtual Token Transfers */
341
+ vfills_S_A.generate_r1cs_witness ();
342
+ vfills_B_A.generate_r1cs_witness ();
343
+ vfills_S_B.generate_r1cs_witness ();
344
+ vfills_B_B.generate_r1cs_witness ();
345
+ update_vbalanceS_A.generate_r1cs_witness ();
346
+ update_vbalanceB_A.generate_r1cs_witness ();
347
+ update_vbalanceS_B.generate_r1cs_witness ();
348
+ update_vbalanceB_B.generate_r1cs_witness ();
349
+
282
350
// AMM validation
283
351
validateAMM.generate_r1cs_witness ();
284
352
}
@@ -299,6 +367,12 @@ class SpotTradeCircuit : public BaseTransactionCircuit
299
367
balanceA_O.generate_r1cs_constraints ();
300
368
balanceB_O.generate_r1cs_constraints ();
301
369
370
+ // Virtual balances
371
+ vbalanceS_A.generate_r1cs_constraints ();
372
+ vbalanceB_A.generate_r1cs_constraints ();
373
+ vbalanceS_B.generate_r1cs_constraints ();
374
+ vbalanceB_B.generate_r1cs_constraints ();
375
+
302
376
// Order fills
303
377
fillS_A.generate_r1cs_constraints ();
304
378
fillS_B.generate_r1cs_constraints ();
@@ -326,6 +400,16 @@ class SpotTradeCircuit : public BaseTransactionCircuit
326
400
protocolFeeA_from_balanceAO_to_balanceAP.generate_r1cs_constraints ();
327
401
protocolFeeB_from_balanceBO_to_balanceBP.generate_r1cs_constraints ();
328
402
403
+ /* Virtual Token Transfers */
404
+ vfills_S_A.generate_r1cs_constraints ();
405
+ vfills_B_A.generate_r1cs_constraints ();
406
+ vfills_S_B.generate_r1cs_constraints ();
407
+ vfills_B_B.generate_r1cs_constraints ();
408
+ update_vbalanceS_A.generate_r1cs_constraints ();
409
+ update_vbalanceB_A.generate_r1cs_constraints ();
410
+ update_vbalanceS_B.generate_r1cs_constraints ();
411
+ update_vbalanceB_B.generate_r1cs_constraints ();
412
+
329
413
// AMM validation
330
414
validateAMM.generate_r1cs_constraints ();
331
415
}
0 commit comments