@evvm/testnet-contracts 2.2.3 → 2.3.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.
Files changed (34) hide show
  1. package/LICENSE +145 -118
  2. package/README.md +138 -35
  3. package/contracts/evvm/Evvm.sol +154 -181
  4. package/contracts/evvm/lib/ErrorsLib.sol +119 -6
  5. package/contracts/evvm/lib/EvvmStorage.sol +164 -9
  6. package/contracts/evvm/lib/EvvmStructs.sol +124 -6
  7. package/contracts/evvm/lib/SignatureUtils.sol +103 -61
  8. package/contracts/nameService/NameService.sol +165 -155
  9. package/contracts/nameService/lib/ErrorsLib.sol +142 -8
  10. package/contracts/nameService/lib/IdentityValidation.sol +21 -0
  11. package/contracts/nameService/lib/NameServiceStructs.sol +75 -19
  12. package/contracts/nameService/lib/SignatureUtils.sol +235 -60
  13. package/contracts/p2pSwap/P2PSwap.sol +201 -160
  14. package/contracts/staking/Estimator.sol +131 -24
  15. package/contracts/staking/Staking.sol +98 -113
  16. package/contracts/staking/lib/ErrorsLib.sol +79 -3
  17. package/contracts/staking/lib/SignatureUtils.sol +82 -16
  18. package/contracts/staking/lib/StakingStructs.sol +12 -0
  19. package/contracts/treasury/Treasury.sol +30 -12
  20. package/contracts/treasury/lib/ErrorsLib.sol +30 -0
  21. package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +3 -3
  22. package/interfaces/IEvvm.sol +9 -4
  23. package/interfaces/INameService.sol +12 -3
  24. package/interfaces/IStaking.sol +2 -1
  25. package/library/Erc191TestBuilder.sol +188 -0
  26. package/library/EvvmService.sol +55 -0
  27. package/library/primitives/SignatureRecover.sol +33 -0
  28. package/library/utils/AdvancedStrings.sol +61 -0
  29. package/library/utils/SignatureUtil.sol +34 -0
  30. package/library/utils/nonces/AsyncNonce.sol +42 -0
  31. package/library/utils/nonces/SyncNonce.sol +44 -0
  32. package/library/utils/service/EvvmPayments.sol +65 -0
  33. package/library/utils/service/StakingServiceUtils.sol +44 -0
  34. package/package.json +2 -1
@@ -168,17 +168,11 @@ contract P2PSwap is
168
168
  // send the executor the priorityFee
169
169
  makeCaPay(msg.sender, metadata.tokenA, _priorityFee_Evvm);
170
170
  }
171
-
172
- // send some mate token reward to the executor (independent of the priorityFee the user attached)
173
- makeCaPay(
174
- msg.sender,
175
- MATE_TOKEN_ADDRESS,
176
- _priorityFee_Evvm > 0
177
- ? (evvm.getRewardAmount() * 3)
178
- : (evvm.getRewardAmount() * 2)
179
- );
180
171
  }
181
172
 
173
+ // send some mate token reward to the executor (independent of the priorityFee the user attached)
174
+ _rewardExecutor(msg.sender, _priorityFee_Evvm > 0 ? 3 : 2);
175
+
182
176
  markAsyncNonceAsUsed(user, metadata.nonce);
183
177
  }
184
178
 
@@ -208,12 +202,7 @@ contract P2PSwap is
208
202
 
209
203
  verifyAsyncNonce(user, metadata.nonce);
210
204
 
211
- if (
212
- market == 0 ||
213
- ordersInsideMarket[market][metadata.orderId].seller != user
214
- ) {
215
- revert("Invalid order");
216
- }
205
+ _validateOrderOwnership(market, metadata.orderId, user);
217
206
 
218
207
  if (_priorityFee_Evvm > 0) {
219
208
  requestPay(
@@ -233,18 +222,13 @@ contract P2PSwap is
233
222
  ordersInsideMarket[market][metadata.orderId].amountA
234
223
  );
235
224
 
236
- ordersInsideMarket[market][metadata.orderId].seller = address(0);
225
+ _clearOrderAndUpdateMarket(market, metadata.orderId);
237
226
 
238
- if (evvm.isAddressStaker(msg.sender)) {
239
- makeCaPay(
240
- msg.sender,
241
- MATE_TOKEN_ADDRESS,
242
- _priorityFee_Evvm > 0
243
- ? ((evvm.getRewardAmount() * 3) + _priorityFee_Evvm)
244
- : (evvm.getRewardAmount() * 2)
245
- );
227
+ if (evvm.isAddressStaker(msg.sender) && _priorityFee_Evvm > 0) {
228
+ makeCaPay(msg.sender, MATE_TOKEN_ADDRESS, _priorityFee_Evvm);
246
229
  }
247
- marketMetadata[market].ordersAvailable--;
230
+ _rewardExecutor(msg.sender, _priorityFee_Evvm > 0 ? 3 : 2);
231
+
248
232
  markAsyncNonceAsUsed(user, metadata.nonce);
249
233
  }
250
234
 
@@ -274,21 +258,12 @@ contract P2PSwap is
274
258
 
275
259
  verifyAsyncNonce(user, metadata.nonce);
276
260
 
277
- if (
278
- market == 0 ||
279
- ordersInsideMarket[market][metadata.orderId].seller == address(0)
280
- ) {
281
- revert("Invalid order");
282
- }
261
+ Order storage order = _validateMarketAndOrder(market, metadata.orderId);
283
262
 
284
- uint256 fee = calculateFillPropotionalFee(
285
- ordersInsideMarket[market][metadata.orderId].amountB
286
- );
263
+ uint256 fee = calculateFillPropotionalFee(order.amountB);
264
+ uint256 requiredAmount = order.amountB + fee;
287
265
 
288
- if (
289
- metadata.amountOfTokenBToFill <
290
- ordersInsideMarket[market][metadata.orderId].amountB + fee
291
- ) {
266
+ if (metadata.amountOfTokenBToFill < requiredAmount) {
292
267
  revert("Insuficient amountOfTokenToFill");
293
268
  }
294
269
 
@@ -303,67 +278,29 @@ contract P2PSwap is
303
278
  );
304
279
 
305
280
  // si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
306
- if (
307
- metadata.amountOfTokenBToFill >
308
- ordersInsideMarket[market][metadata.orderId].amountB + fee
309
- ) {
310
- makeCaPay(
311
- user,
312
- metadata.tokenB,
313
- metadata.amountOfTokenBToFill -
314
- (ordersInsideMarket[market][metadata.orderId].amountB + fee)
315
- );
316
- }
317
-
318
- EvvmStructs.DisperseCaPayMetadata[]
319
- memory toData = new EvvmStructs.DisperseCaPayMetadata[](2);
320
-
321
- uint256 sellerAmount = ordersInsideMarket[market][metadata.orderId]
322
- .amountB + ((fee * rewardPercentage.seller) / 10_000);
323
- uint256 executorAmount = _priorityFee_Evvm +
324
- ((fee * rewardPercentage.mateStaker) / 10_000);
325
-
326
- // pay seller
327
- toData[0] = EvvmStructs.DisperseCaPayMetadata(
328
- sellerAmount,
329
- ordersInsideMarket[market][metadata.orderId].seller
330
- );
331
- // pay executor
332
- toData[1] = EvvmStructs.DisperseCaPayMetadata(
333
- executorAmount,
334
- msg.sender
281
+ bool didRefund = _handleOverpaymentRefund(
282
+ user,
283
+ metadata.tokenB,
284
+ metadata.amountOfTokenBToFill,
285
+ requiredAmount
335
286
  );
336
287
 
337
- balancesOfContract[metadata.tokenB] +=
338
- (fee * rewardPercentage.service) /
339
- 10_000;
340
-
341
- makeDisperseCaPay(
342
- toData,
288
+ // distribute payments to seller and executor
289
+ _distributePayments(
343
290
  metadata.tokenB,
344
- toData[0].amount + toData[1].amount
291
+ order.amountB,
292
+ fee,
293
+ order.seller,
294
+ msg.sender,
295
+ _priorityFee_Evvm
345
296
  );
346
297
 
347
298
  // pay user with token A
348
- makeCaPay(
349
- user,
350
- metadata.tokenA,
351
- ordersInsideMarket[market][metadata.orderId].amountA
352
- );
299
+ makeCaPay(user, metadata.tokenA, order.amountA);
353
300
 
354
- if (evvm.isAddressStaker(msg.sender)) {
355
- makeCaPay(
356
- msg.sender,
357
- MATE_TOKEN_ADDRESS,
358
- metadata.amountOfTokenBToFill >
359
- ordersInsideMarket[market][metadata.orderId].amountB + fee
360
- ? evvm.getRewardAmount() * 5
361
- : evvm.getRewardAmount() * 4
362
- );
363
- }
301
+ _rewardExecutor(msg.sender, didRefund ? 5 : 4);
364
302
 
365
- ordersInsideMarket[market][metadata.orderId].seller = address(0);
366
- marketMetadata[market].ordersAvailable--;
303
+ _clearOrderAndUpdateMarket(market, metadata.orderId);
367
304
  markAsyncNonceAsUsed(user, metadata.nonce);
368
305
  }
369
306
 
@@ -394,22 +331,17 @@ contract P2PSwap is
394
331
 
395
332
  verifyAsyncNonce(user, metadata.nonce);
396
333
 
397
- if (
398
- market == 0 ||
399
- ordersInsideMarket[market][metadata.orderId].seller == address(0)
400
- ) {
401
- revert("Invalid order");
402
- }
334
+ Order storage order = _validateMarketAndOrder(market, metadata.orderId);
403
335
 
404
336
  (uint256 fee, uint256 fee10) = calculateFillFixedFee(
405
- ordersInsideMarket[market][metadata.orderId].amountB,
337
+ order.amountB,
406
338
  maxFillFixedFee
407
339
  );
408
340
 
409
- if (
410
- metadata.amountOfTokenBToFill <
411
- ordersInsideMarket[market][metadata.orderId].amountB + fee - fee10
412
- ) {
341
+ uint256 minRequired = order.amountB + fee - fee10;
342
+ uint256 fullRequired = order.amountB + fee;
343
+
344
+ if (metadata.amountOfTokenBToFill < minRequired) {
413
345
  revert("Insuficient amountOfTokenBToFill");
414
346
  }
415
347
 
@@ -423,76 +355,39 @@ contract P2PSwap is
423
355
  _signature_Evvm
424
356
  );
425
357
 
426
- uint256 finalFee = metadata.amountOfTokenBToFill >=
427
- ordersInsideMarket[market][metadata.orderId].amountB +
428
- fee -
429
- fee10 &&
430
- metadata.amountOfTokenBToFill <
431
- ordersInsideMarket[market][metadata.orderId].amountB + fee
432
- ? metadata.amountOfTokenBToFill -
433
- ordersInsideMarket[market][metadata.orderId].amountB
434
- : fee;
358
+ uint256 finalFee = _calculateFinalFee(
359
+ metadata.amountOfTokenBToFill,
360
+ order.amountB,
361
+ fee,
362
+ fee10
363
+ );
435
364
 
436
365
  // si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
437
- if (
438
- metadata.amountOfTokenBToFill >
439
- ordersInsideMarket[market][metadata.orderId].amountB + fee
440
- ) {
441
- makeCaPay(
442
- user,
443
- metadata.tokenB,
444
- metadata.amountOfTokenBToFill -
445
- (ordersInsideMarket[market][metadata.orderId].amountB + fee)
446
- );
447
- }
448
-
449
- EvvmStructs.DisperseCaPayMetadata[]
450
- memory toData = new EvvmStructs.DisperseCaPayMetadata[](2);
451
-
452
- toData[0] = EvvmStructs.DisperseCaPayMetadata(
453
- ordersInsideMarket[market][metadata.orderId].amountB +
454
- ((finalFee * rewardPercentage.seller) / 10_000),
455
- ordersInsideMarket[market][metadata.orderId].seller
456
- );
457
- toData[1] = EvvmStructs.DisperseCaPayMetadata(
458
- _priorityFee_Evvm +
459
- ((finalFee * rewardPercentage.mateStaker) / 10_000),
460
- msg.sender
366
+ bool didRefund = _handleOverpaymentRefund(
367
+ user,
368
+ metadata.tokenB,
369
+ metadata.amountOfTokenBToFill,
370
+ fullRequired
461
371
  );
462
372
 
463
- balancesOfContract[metadata.tokenB] +=
464
- (finalFee * rewardPercentage.service) /
465
- 10_000;
466
-
467
- makeDisperseCaPay(
468
- toData,
373
+ // distribute payments to seller and executor
374
+ _distributePayments(
469
375
  metadata.tokenB,
470
- toData[0].amount + toData[1].amount
376
+ order.amountB,
377
+ finalFee,
378
+ order.seller,
379
+ msg.sender,
380
+ _priorityFee_Evvm
471
381
  );
472
382
 
473
- makeCaPay(
474
- user,
475
- metadata.tokenA,
476
- ordersInsideMarket[market][metadata.orderId].amountA
477
- );
383
+ makeCaPay(user, metadata.tokenA, order.amountA);
478
384
 
479
- if (evvm.isAddressStaker(msg.sender)) {
480
- makeCaPay(
481
- msg.sender,
482
- MATE_TOKEN_ADDRESS,
483
- metadata.amountOfTokenBToFill >
484
- ordersInsideMarket[market][metadata.orderId].amountB + fee
485
- ? evvm.getRewardAmount() * 5
486
- : evvm.getRewardAmount() * 4
487
- );
488
- }
385
+ _rewardExecutor(msg.sender, didRefund ? 5 : 4);
489
386
 
490
- ordersInsideMarket[market][metadata.orderId].seller = address(0);
491
- marketMetadata[market].ordersAvailable--;
387
+ _clearOrderAndUpdateMarket(market, metadata.orderId);
492
388
  markAsyncNonceAsUsed(user, metadata.nonce);
493
389
  }
494
390
 
495
- //devolver el 0.05% del monto de la orden
496
391
  function calculateFillPropotionalFee(
497
392
  uint256 amount
498
393
  ) internal view returns (uint256 fee) {
@@ -512,6 +407,152 @@ contract P2PSwap is
512
407
  }
513
408
  }
514
409
 
410
+ /**
411
+ * @dev Calculates the final fee for fixed fee dispatch considering tolerance range
412
+ * @param amountPaid Amount paid by user
413
+ * @param orderAmount Base order amount
414
+ * @param fee Full fee amount
415
+ * @param fee10 10% tolerance of fee
416
+ * @return finalFee The calculated final fee
417
+ */
418
+ function _calculateFinalFee(
419
+ uint256 amountPaid,
420
+ uint256 orderAmount,
421
+ uint256 fee,
422
+ uint256 fee10
423
+ ) internal pure returns (uint256 finalFee) {
424
+ uint256 minRequired = orderAmount + fee - fee10;
425
+ uint256 fullRequired = orderAmount + fee;
426
+
427
+ if (amountPaid >= minRequired && amountPaid < fullRequired) {
428
+ finalFee = amountPaid - orderAmount;
429
+ } else {
430
+ finalFee = fee;
431
+ }
432
+ }
433
+
434
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
435
+ // Internal helper functions to avoid Stack too deep
436
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
437
+
438
+ /**
439
+ * @dev Validates that a market and order exist and are valid
440
+ * @param market The market ID
441
+ * @param orderId The order ID within the market
442
+ * @return order The order data if valid
443
+ */
444
+ function _validateMarketAndOrder(
445
+ uint256 market,
446
+ uint256 orderId
447
+ ) internal view returns (Order storage order) {
448
+ if (market == 0) {
449
+ revert("Invalid order");
450
+ }
451
+ order = ordersInsideMarket[market][orderId];
452
+ if (order.seller == address(0)) {
453
+ revert("Invalid order");
454
+ }
455
+ }
456
+
457
+ /**
458
+ * @dev Validates that a market exists and the user is the seller of the order
459
+ * @param market The market ID
460
+ * @param orderId The order ID
461
+ * @param user The expected seller address
462
+ */
463
+ function _validateOrderOwnership(
464
+ uint256 market,
465
+ uint256 orderId,
466
+ address user
467
+ ) internal view {
468
+ if (
469
+ market == 0 ||
470
+ ordersInsideMarket[market][orderId].seller != user
471
+ ) {
472
+ revert("Invalid order");
473
+ }
474
+ }
475
+
476
+ /**
477
+ * @dev Rewards the executor (staker) with MATE tokens based on operation complexity
478
+ * @param executor The address of the executor
479
+ * @param multiplier The reward multiplier (2, 3, 4, or 5)
480
+ */
481
+ function _rewardExecutor(address executor, uint256 multiplier) internal {
482
+ if (evvm.isAddressStaker(executor)) {
483
+ makeCaPay(
484
+ executor,
485
+ MATE_TOKEN_ADDRESS,
486
+ evvm.getRewardAmount() * multiplier
487
+ );
488
+ }
489
+ }
490
+
491
+ /**
492
+ * @dev Clears an order and updates market metadata
493
+ * @param market The market ID
494
+ * @param orderId The order ID to clear
495
+ */
496
+ function _clearOrderAndUpdateMarket(
497
+ uint256 market,
498
+ uint256 orderId
499
+ ) internal {
500
+ ordersInsideMarket[market][orderId].seller = address(0);
501
+ marketMetadata[market].ordersAvailable--;
502
+ }
503
+
504
+ /**
505
+ * @dev Handles refund to user if they overpaid
506
+ * @param user The user address to refund
507
+ * @param token The token address
508
+ * @param amountPaid The amount the user paid
509
+ * @param amountRequired The required amount (order amount + fee)
510
+ * @return didRefund Whether a refund was made
511
+ */
512
+ function _handleOverpaymentRefund(
513
+ address user,
514
+ address token,
515
+ uint256 amountPaid,
516
+ uint256 amountRequired
517
+ ) internal returns (bool didRefund) {
518
+ if (amountPaid > amountRequired) {
519
+ makeCaPay(user, token, amountPaid - amountRequired);
520
+ return true;
521
+ }
522
+ return false;
523
+ }
524
+
525
+ /**
526
+ * @dev Distributes payment to seller and executor, and accumulates service fee
527
+ * @param token The token address for payment
528
+ * @param orderAmount The base order amount
529
+ * @param fee The fee amount to distribute
530
+ * @param seller The seller address
531
+ * @param executor The executor address
532
+ * @param priorityFee The priority fee for executor
533
+ */
534
+ function _distributePayments(
535
+ address token,
536
+ uint256 orderAmount,
537
+ uint256 fee,
538
+ address seller,
539
+ address executor,
540
+ uint256 priorityFee
541
+ ) internal {
542
+ uint256 sellerAmount = orderAmount + ((fee * rewardPercentage.seller) / 10_000);
543
+ uint256 executorAmount = priorityFee + ((fee * rewardPercentage.mateStaker) / 10_000);
544
+
545
+ EvvmStructs.DisperseCaPayMetadata[]
546
+ memory toData = new EvvmStructs.DisperseCaPayMetadata[](2);
547
+
548
+ toData[0] = EvvmStructs.DisperseCaPayMetadata(sellerAmount, seller);
549
+ toData[1] = EvvmStructs.DisperseCaPayMetadata(executorAmount, executor);
550
+
551
+ balancesOfContract[token] += (fee * rewardPercentage.service) / 10_000;
552
+
553
+ makeDisperseCaPay(toData, token, sellerAmount + executorAmount);
554
+ }
555
+
515
556
  function createMarket(
516
557
  address tokenA,
517
558
  address tokenB