@evvm/testnet-contracts 2.0.4 → 2.1.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.
@@ -0,0 +1,1358 @@
1
+ // SPDX-License-Identifier: EVVM-NONCOMMERCIAL-1.0
2
+ // Full license terms available at: https://www.evvm.org/docs/EVVMNoncommercialLicense
3
+
4
+ pragma solidity ^0.8.0;
5
+ /**
6
+ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
7
+ | $$__ $$/$$__ $| $$__ $$/$$__ $$
8
+ | $$ \ $|__/ \ $| $$ \ $| $$ \__//$$ /$$ /$$ /$$$$$$ /$$$$$$
9
+ | $$$$$$$/ /$$$$$$| $$$$$$$| $$$$$$| $$ | $$ | $$|____ $$/$$__ $$
10
+ | $$____/ /$$____/| $$____/ \____ $| $$ | $$ | $$ /$$$$$$| $$ \ $$
11
+ | $$ | $$ | $$ /$$ \ $| $$ | $$ | $$/$$__ $| $$ | $$
12
+ | $$ | $$$$$$$| $$ | $$$$$$| $$$$$/$$$$| $$$$$$| $$$$$$$/
13
+ |__/ |________|__/ \______/ \_____/\___/ \_______| $$____/
14
+ | $$
15
+ | $$
16
+ |__/
17
+
18
+ * @title P2P Swap Service
19
+ * @author Mate labs
20
+ * @notice Peer-to-peer decentralized exchange for token trading within the EVVM ecosystem
21
+ * @dev Implements order book-style trading with dynamic market creation, fee distribution,
22
+ * and integration with EVVM's staking and payment systems. Supports both proportional
23
+ * and fixed fee models with time-delayed governance for parameter updates.
24
+ *
25
+ * Key Features:
26
+ * - Dynamic market creation for any token pair
27
+ * - Order management (create, cancel, execute)
28
+ * - Configurable fee structure with multi-party distribution
29
+ * - Service staking capabilities via StakingServiceHooks inheritance
30
+ * - ERC-191 signature verification for all operations
31
+ * - Time-delayed administrative governance
32
+ *
33
+ * Fee Distribution:
34
+ * - Seller: 50% (configurable)
35
+ * - Service: 40% (configurable)
36
+ * - Staker Rewards: 10% (configurable)
37
+ */
38
+
39
+ import {Evvm} from "@evvm/testnet-contracts/contracts/evvm/Evvm.sol";
40
+ import {Staking} from "@evvm/testnet-contracts/contracts/staking/Staking.sol";
41
+ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
42
+ import {SignatureRecover} from "@evvm/testnet-contracts/library/SignatureRecover.sol";
43
+ import {SignatureUtils} from "@evvm/testnet-contracts/contracts/p2pSwap/lib/SignatureUtils.sol";
44
+ import {AdvancedStrings} from "@evvm/testnet-contracts/library/AdvancedStrings.sol";
45
+ import {EvvmStructs} from "@evvm/testnet-contracts/contracts/evvm/lib/EvvmStructs.sol";
46
+ import {StakingServiceHooks} from "@evvm/testnet-contracts/library/StakingServiceHooks.sol";
47
+
48
+ contract P2PSwap is StakingServiceHooks {
49
+ using SignatureRecover for *;
50
+ using AdvancedStrings for *;
51
+
52
+ /// @notice Current contract owner with administrative privileges
53
+ address owner;
54
+ /// @notice Proposed new owner address pending acceptance
55
+ address owner_proposal;
56
+ /// @notice Timestamp when the proposed owner change can be accepted
57
+ uint256 owner_timeToAccept;
58
+
59
+ /// @notice Address of the EVVM core contract for payment processing
60
+ address evvmAddress;
61
+ /// @notice Address of the Staking contract for service staking functionality
62
+ address stakingAddress;
63
+
64
+ /// @notice Constant address representing the MATE token (Principal Token)
65
+ address constant MATE_TOKEN_ADDRESS =
66
+ 0x0000000000000000000000000000000000000001;
67
+ /// @notice Constant address representing native ETH
68
+ address constant ETH_ADDRESS = 0x0000000000000000000000000000000000000000;
69
+
70
+ /**
71
+ * @notice Market metadata containing token pair and order tracking information
72
+ * @param tokenA Address of the first token in the trading pair
73
+ * @param tokenB Address of the second token in the trading pair
74
+ * @param maxSlot Maximum order ID ever created in this market
75
+ * @param ordersAvailable Current number of active orders in the market
76
+ */
77
+ struct MarketInformation {
78
+ address tokenA;
79
+ address tokenB;
80
+ uint256 maxSlot;
81
+ uint256 ordersAvailable;
82
+ }
83
+
84
+ /**
85
+ * @notice Individual order details within a market
86
+ * @param seller Address of the user who created the order
87
+ * @param amountA Amount of tokenA the seller is offering
88
+ * @param amountB Amount of tokenB the seller wants in return
89
+ */
90
+ struct Order {
91
+ address seller;
92
+ uint256 amountA;
93
+ uint256 amountB;
94
+ }
95
+
96
+ /**
97
+ * @notice Extended order information for external queries
98
+ * @param marketId ID of the market containing this order
99
+ * @param orderId Unique order ID within the market
100
+ * @param seller Address of the user who created the order
101
+ * @param amountA Amount of tokenA being offered
102
+ * @param amountB Amount of tokenB being requested
103
+ */
104
+ struct OrderForGetter {
105
+ uint256 marketId;
106
+ uint256 orderId;
107
+ address seller;
108
+ uint256 amountA;
109
+ uint256 amountB;
110
+ }
111
+
112
+ /**
113
+ * @notice Fee distribution percentages (in basis points, total must equal 10,000)
114
+ * @param seller Percentage of fees distributed to the order seller
115
+ * @param service Percentage of fees retained by the P2PSwap service
116
+ * @param mateStaker Percentage of fees distributed to MATE token stakers
117
+ */
118
+ struct Percentage {
119
+ uint256 seller;
120
+ uint256 service;
121
+ uint256 mateStaker;
122
+ }
123
+
124
+ /**
125
+ * @notice Metadata required for creating a new order
126
+ * @param nonce Unique nonce to prevent replay attacks
127
+ * @param tokenA Address of the token being offered
128
+ * @param tokenB Address of the token being requested
129
+ * @param amountA Amount of tokenA to offer
130
+ * @param amountB Amount of tokenB requested in return
131
+ */
132
+ struct MetadataMakeOrder {
133
+ uint256 nonce;
134
+ address tokenA;
135
+ address tokenB;
136
+ uint256 amountA;
137
+ uint256 amountB;
138
+ }
139
+
140
+ /**
141
+ * @notice Metadata required for canceling an existing order
142
+ * @param nonce Unique nonce to prevent replay attacks
143
+ * @param tokenA Address of the first token in the market
144
+ * @param tokenB Address of the second token in the market
145
+ * @param orderId ID of the order to cancel
146
+ * @param signature User's signature authorizing the cancellation
147
+ */
148
+ struct MetadataCancelOrder {
149
+ uint256 nonce;
150
+ address tokenA;
151
+ address tokenB;
152
+ uint256 orderId;
153
+ bytes signature;
154
+ }
155
+
156
+ /**
157
+ * @notice Metadata required for executing/filling an order
158
+ * @param nonce Unique nonce to prevent replay attacks
159
+ * @param tokenA Address of the first token in the market
160
+ * @param tokenB Address of the second token in the market
161
+ * @param orderId ID of the order to execute
162
+ * @param amountOfTokenBToFill Amount of tokenB to pay (including fees)
163
+ * @param signature User's signature authorizing the execution
164
+ */
165
+ struct MetadataDispatchOrder {
166
+ uint256 nonce;
167
+ address tokenA;
168
+ address tokenB;
169
+ uint256 orderId;
170
+ uint256 amountOfTokenBToFill;
171
+ bytes signature;
172
+ }
173
+
174
+ /// @notice Current fee distribution percentages
175
+ Percentage rewardPercentage;
176
+ /// @notice Proposed new fee distribution percentages
177
+ Percentage rewardPercentage_proposal;
178
+ /// @notice Timestamp when reward percentage change can be accepted
179
+ uint256 rewardPercentage_timeToAcceptNewChange;
180
+
181
+ /// @notice Current trading fee percentage (in basis points)
182
+ uint256 percentageFee;
183
+ /// @notice Proposed new trading fee percentage
184
+ uint256 percentageFee_proposal;
185
+ /// @notice Timestamp when fee percentage change can be accepted
186
+ uint256 percentageFee_timeToAccept;
187
+
188
+ /// @notice Maximum fixed fee limit for order execution
189
+ uint256 maxLimitFillFixedFee;
190
+ /// @notice Proposed new maximum fixed fee limit
191
+ uint256 maxLimitFillFixedFee_proposal;
192
+ /// @notice Timestamp when max fee limit change can be accepted
193
+ uint256 maxLimitFillFixedFee_timeToAccept;
194
+
195
+ /// @notice Token address for pending withdrawal
196
+ address tokenToWithdraw;
197
+ /// @notice Amount for pending withdrawal
198
+ uint256 amountToWithdraw;
199
+ /// @notice Recipient address for pending withdrawal
200
+ address recipientToWithdraw;
201
+ /// @notice Timestamp when withdrawal can be executed
202
+ uint256 timeToWithdrawal;
203
+
204
+ /// @notice Total number of markets created
205
+ uint256 marketCount;
206
+
207
+ /// @notice Tracks used nonces per user to prevent replay attacks
208
+ mapping(address user => mapping(uint256 nonce => bool isUsed)) nonceP2PSwap;
209
+
210
+ /// @notice Maps token pairs to their market ID
211
+ mapping(address tokenA => mapping(address tokenB => uint256 id)) marketId;
212
+
213
+ /// @notice Stores market information by market ID
214
+ mapping(uint256 id => MarketInformation info) marketMetadata;
215
+
216
+ /// @notice Stores orders within each market
217
+ mapping(uint256 idMarket => mapping(uint256 idOrder => Order)) ordersInsideMarket;
218
+
219
+ /// @notice Tracks service fee balances accumulated per token
220
+ mapping(address => uint256) balancesOfContract;
221
+
222
+ /**
223
+ * @notice Initializes the P2PSwap contract with required addresses and default parameters
224
+ * @param _evvmAddress Address of the EVVM core contract for payment processing
225
+ * @param _stakingAddress Address of the Staking contract for service functionality
226
+ * @param _owner Address that will have administrative privileges
227
+ */
228
+ constructor(
229
+ address _evvmAddress,
230
+ address _stakingAddress,
231
+ address _owner
232
+ ) StakingServiceHooks(_stakingAddress) {
233
+ evvmAddress = _evvmAddress;
234
+ owner = _owner;
235
+ maxLimitFillFixedFee = 0.001 ether;
236
+ percentageFee = 500;
237
+ rewardPercentage = Percentage({
238
+ seller: 5000,
239
+ service: 4000,
240
+ mateStaker: 1000
241
+ });
242
+ stakingAddress = _stakingAddress;
243
+ }
244
+
245
+ /**
246
+ * @notice Creates a new trading order in the specified market
247
+ * @dev Verifies signature, processes payment, creates/finds market, and assigns order slot
248
+ * @param user Address of the user creating the order
249
+ * @param metadata Order details including tokens, amounts, and nonce
250
+ * @param signature User's signature authorizing the order creation
251
+ * @param _priorityFee_Evvm Priority fee for EVVM transaction processing
252
+ * @param _nonce_Evvm Nonce for EVVM payment transaction
253
+ * @param _priority_Evvm Whether to use priority (async) processing
254
+ * @param _signature_Evvm Signature for EVVM payment authorization
255
+ * @return market ID of the market where order was created
256
+ * @return orderId Unique ID of the created order within the market
257
+ */
258
+ function makeOrder(
259
+ address user,
260
+ MetadataMakeOrder memory metadata,
261
+ bytes memory signature,
262
+ uint256 _priorityFee_Evvm,
263
+ uint256 _nonce_Evvm,
264
+ bool _priority_Evvm,
265
+ bytes memory _signature_Evvm
266
+ ) external returns (uint256 market, uint256 orderId) {
267
+ if (
268
+ !SignatureUtils.verifyMessageSignedForMakeOrder(
269
+ Evvm(evvmAddress).getEvvmID(),
270
+ user,
271
+ metadata.nonce,
272
+ metadata.tokenA,
273
+ metadata.tokenB,
274
+ metadata.amountA,
275
+ metadata.amountB,
276
+ signature
277
+ )
278
+ ) {
279
+ revert("Invalid signature");
280
+ }
281
+
282
+ if (nonceP2PSwap[user][metadata.nonce]) {
283
+ revert("Nonce already used");
284
+ }
285
+
286
+ makePay(
287
+ user,
288
+ metadata.tokenA,
289
+ _nonce_Evvm,
290
+ metadata.amountA,
291
+ _priorityFee_Evvm,
292
+ _priority_Evvm,
293
+ _signature_Evvm
294
+ );
295
+
296
+ market = findMarket(metadata.tokenA, metadata.tokenB);
297
+ if (market == 0) {
298
+ market = createMarket(metadata.tokenA, metadata.tokenB);
299
+ }
300
+
301
+ if (
302
+ marketMetadata[market].maxSlot ==
303
+ marketMetadata[market].ordersAvailable
304
+ ) {
305
+ marketMetadata[market].maxSlot++;
306
+ marketMetadata[market].ordersAvailable++;
307
+ orderId = marketMetadata[market].maxSlot;
308
+ } else {
309
+ for (uint256 i = 1; i <= marketMetadata[market].maxSlot + 1; i++) {
310
+ if (ordersInsideMarket[market][i].seller == address(0)) {
311
+ orderId = i;
312
+ break;
313
+ }
314
+ }
315
+ marketMetadata[market].ordersAvailable++;
316
+ }
317
+
318
+ ordersInsideMarket[market][orderId] = Order(
319
+ user,
320
+ metadata.amountA,
321
+ metadata.amountB
322
+ );
323
+
324
+ if (Evvm(evvmAddress).isAddressStaker(msg.sender)) {
325
+ if (_priorityFee_Evvm > 0) {
326
+ // send the executor the priorityFee
327
+ makeCaPay(msg.sender, metadata.tokenA, _priorityFee_Evvm);
328
+ }
329
+
330
+ // send some mate token reward to the executor (independent of the priorityFee the user attached)
331
+ makeCaPay(
332
+ msg.sender,
333
+ MATE_TOKEN_ADDRESS,
334
+ _priorityFee_Evvm > 0
335
+ ? (Evvm(evvmAddress).getRewardAmount() * 3)
336
+ : (Evvm(evvmAddress).getRewardAmount() * 2)
337
+ );
338
+ }
339
+
340
+ nonceP2PSwap[user][metadata.nonce] = true;
341
+ }
342
+
343
+ /**
344
+ * @notice Cancels an existing order and refunds tokens to the seller
345
+ * @dev Verifies signature, validates ownership, refunds tokenA, and removes order
346
+ * @param user Address of the user canceling the order
347
+ * @param metadata Cancel details including market info and order ID
348
+ * @param _priorityFee_Evvm Priority fee for EVVM transaction (optional)
349
+ * @param _nonce_Evvm Nonce for EVVM payment transaction (if priority fee > 0)
350
+ * @param _priority_Evvm Whether to use priority processing
351
+ * @param _signature_Evvm Signature for EVVM payment (if priority fee > 0)
352
+ */
353
+ function cancelOrder(
354
+ address user,
355
+ MetadataCancelOrder memory metadata,
356
+ uint256 _priorityFee_Evvm,
357
+ uint256 _nonce_Evvm,
358
+ bool _priority_Evvm,
359
+ bytes memory _signature_Evvm
360
+ ) external {
361
+ if (
362
+ !SignatureUtils.verifyMessageSignedForCancelOrder(
363
+ Evvm(evvmAddress).getEvvmID(),
364
+ user,
365
+ metadata.nonce,
366
+ metadata.tokenA,
367
+ metadata.tokenB,
368
+ metadata.orderId,
369
+ metadata.signature
370
+ )
371
+ ) {
372
+ revert("Invalid signature");
373
+ }
374
+
375
+ uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
376
+
377
+ if (nonceP2PSwap[user][metadata.nonce]) {
378
+ revert("Invalid nonce");
379
+ }
380
+
381
+ if (
382
+ market == 0 ||
383
+ ordersInsideMarket[market][metadata.orderId].seller != user
384
+ ) {
385
+ revert("Invalid order");
386
+ }
387
+
388
+ if (_priorityFee_Evvm > 0) {
389
+ makePay(
390
+ user,
391
+ MATE_TOKEN_ADDRESS,
392
+ _nonce_Evvm,
393
+ 0,
394
+ _priorityFee_Evvm,
395
+ _priority_Evvm,
396
+ _signature_Evvm
397
+ );
398
+ }
399
+
400
+ makeCaPay(
401
+ user,
402
+ metadata.tokenA,
403
+ ordersInsideMarket[market][metadata.orderId].amountA
404
+ );
405
+
406
+ ordersInsideMarket[market][metadata.orderId].seller = address(0);
407
+
408
+ if (Evvm(evvmAddress).isAddressStaker(msg.sender)) {
409
+ makeCaPay(
410
+ msg.sender,
411
+ MATE_TOKEN_ADDRESS,
412
+ _priorityFee_Evvm > 0
413
+ ? ((Evvm(evvmAddress).getRewardAmount() * 3) +
414
+ _priorityFee_Evvm)
415
+ : (Evvm(evvmAddress).getRewardAmount() * 2)
416
+ );
417
+ }
418
+ marketMetadata[market].ordersAvailable--;
419
+ nonceP2PSwap[user][metadata.nonce] = true;
420
+ }
421
+
422
+ /**
423
+ * @notice Executes an order using proportional fee calculation
424
+ * @dev Calculates fee as percentage of order amount, distributes payments to all parties
425
+ * @param user Address of the user filling the order
426
+ * @param metadata Execution details including order ID and payment amount
427
+ * @param _priorityFee_Evvm Priority fee for EVVM transaction processing
428
+ * @param _nonce_Evvm Nonce for EVVM payment transaction
429
+ * @param _priority_Evvm Whether to use priority (async) processing
430
+ * @param _signature_Evvm Signature for EVVM payment authorization
431
+ */
432
+ function dispatchOrder_fillPropotionalFee(
433
+ address user,
434
+ MetadataDispatchOrder memory metadata,
435
+ uint256 _priorityFee_Evvm,
436
+ uint256 _nonce_Evvm,
437
+ bool _priority_Evvm,
438
+ bytes memory _signature_Evvm
439
+ ) external {
440
+ if (
441
+ !SignatureUtils.verifyMessageSignedForDispatchOrder(
442
+ Evvm(evvmAddress).getEvvmID(),
443
+ user,
444
+ metadata.nonce,
445
+ metadata.tokenA,
446
+ metadata.tokenB,
447
+ metadata.orderId,
448
+ metadata.signature
449
+ )
450
+ ) {
451
+ revert("Invalid signature");
452
+ }
453
+
454
+ uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
455
+
456
+ if (nonceP2PSwap[user][metadata.nonce]) {
457
+ revert("Invalid nonce");
458
+ }
459
+
460
+ if (
461
+ market == 0 ||
462
+ ordersInsideMarket[market][metadata.orderId].seller == address(0)
463
+ ) {
464
+ revert();
465
+ }
466
+
467
+ uint256 fee = calculateFillPropotionalFee(
468
+ ordersInsideMarket[market][metadata.orderId].amountB
469
+ );
470
+
471
+ if (
472
+ metadata.amountOfTokenBToFill <
473
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
474
+ ) {
475
+ revert("Insuficient amountOfTokenToFill");
476
+ }
477
+
478
+ makePay(
479
+ user,
480
+ metadata.tokenB,
481
+ _nonce_Evvm,
482
+ metadata.amountOfTokenBToFill,
483
+ _priorityFee_Evvm,
484
+ _priority_Evvm,
485
+ _signature_Evvm
486
+ );
487
+
488
+ // si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
489
+ if (
490
+ metadata.amountOfTokenBToFill >
491
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
492
+ ) {
493
+ makeCaPay(
494
+ user,
495
+ metadata.tokenB,
496
+ metadata.amountOfTokenBToFill -
497
+ (ordersInsideMarket[market][metadata.orderId].amountB + fee)
498
+ );
499
+ }
500
+
501
+ EvvmStructs.DisperseCaPayMetadata[]
502
+ memory toData = new EvvmStructs.DisperseCaPayMetadata[](2);
503
+
504
+ uint256 sellerAmount = ordersInsideMarket[market][metadata.orderId]
505
+ .amountB + ((fee * rewardPercentage.seller) / 10_000);
506
+ uint256 executorAmount = _priorityFee_Evvm +
507
+ ((fee * rewardPercentage.mateStaker) / 10_000);
508
+
509
+ // pay seller
510
+ toData[0] = EvvmStructs.DisperseCaPayMetadata(
511
+ sellerAmount,
512
+ ordersInsideMarket[market][metadata.orderId].seller
513
+ );
514
+ // pay executor
515
+ toData[1] = EvvmStructs.DisperseCaPayMetadata(
516
+ executorAmount,
517
+ msg.sender
518
+ );
519
+
520
+ balancesOfContract[metadata.tokenB] +=
521
+ (fee * rewardPercentage.service) /
522
+ 10_000;
523
+
524
+ makeDisperseCaPay(
525
+ toData,
526
+ metadata.tokenB,
527
+ toData[0].amount + toData[1].amount
528
+ );
529
+
530
+ // pay user with token A
531
+ makeCaPay(
532
+ user,
533
+ metadata.tokenA,
534
+ ordersInsideMarket[market][metadata.orderId].amountA
535
+ );
536
+
537
+ if (Evvm(evvmAddress).isAddressStaker(msg.sender)) {
538
+ makeCaPay(
539
+ msg.sender,
540
+ MATE_TOKEN_ADDRESS,
541
+ metadata.amountOfTokenBToFill >
542
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
543
+ ? Evvm(evvmAddress).getRewardAmount() * 5
544
+ : Evvm(evvmAddress).getRewardAmount() * 4
545
+ );
546
+ }
547
+
548
+ ordersInsideMarket[market][metadata.orderId].seller = address(0);
549
+ marketMetadata[market].ordersAvailable--;
550
+ nonceP2PSwap[user][metadata.nonce] = true;
551
+ }
552
+
553
+ /**
554
+ * @notice Executes an order using fixed fee calculation with maximum limits
555
+ * @dev Calculates fee with upper bound, distributes payments, handles overpayment refunds
556
+ * @param user Address of the user filling the order
557
+ * @param metadata Execution details including order ID and payment amount
558
+ * @param _priorityFee_Evvm Priority fee for EVVM transaction processing
559
+ * @param _nonce_Evvm Nonce for EVVM payment transaction
560
+ * @param _priority_Evvm Whether to use priority (async) processing
561
+ * @param _signature_Evvm Signature for EVVM payment authorization
562
+ * @param maxFillFixedFee Maximum output amount for fee calculation (testing parameter)
563
+ */
564
+ function dispatchOrder_fillFixedFee(
565
+ address user,
566
+ MetadataDispatchOrder memory metadata,
567
+ uint256 _priorityFee_Evvm,
568
+ uint256 _nonce_Evvm,
569
+ bool _priority_Evvm,
570
+ bytes memory _signature_Evvm,
571
+ uint256 maxFillFixedFee
572
+ ) external {
573
+ if (
574
+ !SignatureUtils.verifyMessageSignedForDispatchOrder(
575
+ Evvm(evvmAddress).getEvvmID(),
576
+ user,
577
+ metadata.nonce,
578
+ metadata.tokenA,
579
+ metadata.tokenB,
580
+ metadata.orderId,
581
+ metadata.signature
582
+ )
583
+ ) {
584
+ revert();
585
+ }
586
+
587
+ uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
588
+
589
+ if (nonceP2PSwap[user][metadata.nonce]) {
590
+ revert();
591
+ }
592
+
593
+ if (
594
+ market == 0 ||
595
+ ordersInsideMarket[market][metadata.orderId].seller == address(0)
596
+ ) {
597
+ revert();
598
+ }
599
+
600
+ (uint256 fee, uint256 fee10) = calculateFillFixedFee(
601
+ ordersInsideMarket[market][metadata.orderId].amountB,
602
+ maxFillFixedFee
603
+ );
604
+
605
+ if (
606
+ metadata.amountOfTokenBToFill <
607
+ ordersInsideMarket[market][metadata.orderId].amountB + fee - fee10
608
+ ) {
609
+ revert();
610
+ }
611
+
612
+ makePay(
613
+ user,
614
+ metadata.tokenB,
615
+ _nonce_Evvm,
616
+ metadata.amountOfTokenBToFill,
617
+ _priorityFee_Evvm,
618
+ _priority_Evvm,
619
+ _signature_Evvm
620
+ );
621
+
622
+ uint256 finalFee = metadata.amountOfTokenBToFill >=
623
+ ordersInsideMarket[market][metadata.orderId].amountB +
624
+ fee -
625
+ fee10 &&
626
+ metadata.amountOfTokenBToFill <
627
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
628
+ ? metadata.amountOfTokenBToFill -
629
+ ordersInsideMarket[market][metadata.orderId].amountB
630
+ : fee;
631
+
632
+ // si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
633
+ if (
634
+ metadata.amountOfTokenBToFill >
635
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
636
+ ) {
637
+ makeCaPay(
638
+ user,
639
+ metadata.tokenB,
640
+ metadata.amountOfTokenBToFill -
641
+ (ordersInsideMarket[market][metadata.orderId].amountB + fee)
642
+ );
643
+ }
644
+
645
+ EvvmStructs.DisperseCaPayMetadata[]
646
+ memory toData = new EvvmStructs.DisperseCaPayMetadata[](2);
647
+
648
+ toData[0] = EvvmStructs.DisperseCaPayMetadata(
649
+ ordersInsideMarket[market][metadata.orderId].amountB +
650
+ ((finalFee * rewardPercentage.seller) / 10_000),
651
+ ordersInsideMarket[market][metadata.orderId].seller
652
+ );
653
+ toData[1] = EvvmStructs.DisperseCaPayMetadata(
654
+ _priorityFee_Evvm +
655
+ ((finalFee * rewardPercentage.mateStaker) / 10_000),
656
+ msg.sender
657
+ );
658
+
659
+ balancesOfContract[metadata.tokenB] +=
660
+ (finalFee * rewardPercentage.service) /
661
+ 10_000;
662
+
663
+ makeDisperseCaPay(
664
+ toData,
665
+ metadata.tokenB,
666
+ toData[0].amount + toData[1].amount
667
+ );
668
+
669
+ makeCaPay(
670
+ user,
671
+ metadata.tokenA,
672
+ ordersInsideMarket[market][metadata.orderId].amountA
673
+ );
674
+
675
+ if (Evvm(evvmAddress).isAddressStaker(msg.sender)) {
676
+ makeCaPay(
677
+ msg.sender,
678
+ MATE_TOKEN_ADDRESS,
679
+ metadata.amountOfTokenBToFill >
680
+ ordersInsideMarket[market][metadata.orderId].amountB + fee
681
+ ? Evvm(evvmAddress).getRewardAmount() * 5
682
+ : Evvm(evvmAddress).getRewardAmount() * 4
683
+ );
684
+ }
685
+
686
+ ordersInsideMarket[market][metadata.orderId].seller = address(0);
687
+ marketMetadata[market].ordersAvailable--;
688
+ nonceP2PSwap[user][metadata.nonce] = true;
689
+ }
690
+
691
+ /**
692
+ * @notice Calculates proportional trading fee as percentage of order amount
693
+ * @dev Fee is calculated as (amount * percentageFee) / 10,000 basis points
694
+ * @param amount The order amount to calculate fee for
695
+ * @return fee The calculated proportional fee amount
696
+ */
697
+ function calculateFillPropotionalFee(
698
+ uint256 amount
699
+ ) internal view returns (uint256 fee) {
700
+ fee = (amount * percentageFee) / 10_000;
701
+ }
702
+
703
+ /**
704
+ * @notice Calculates fixed trading fee with maximum limit constraints
705
+ * @dev Compares proportional fee with maximum output, applies 10% reduction if needed
706
+ * @param amount Order amount for proportional fee calculation
707
+ * @param maxFillFixedFee Maximum output amount for fee limiting
708
+ * @return fee The final calculated fee amount
709
+ * @return fee10 10% of the fee amount for specific calculations
710
+ */
711
+ function calculateFillFixedFee(
712
+ uint256 amount,
713
+ uint256 maxFillFixedFee
714
+ ) internal view returns (uint256 fee, uint256 fee10) {
715
+ if (calculateFillPropotionalFee(amount) > maxFillFixedFee) {
716
+ fee = maxFillFixedFee;
717
+ fee10 = (fee * 1000) / 10_000;
718
+ } else {
719
+ fee = calculateFillPropotionalFee(amount);
720
+ }
721
+ }
722
+
723
+ /**
724
+ * @notice Creates a new trading market for a token pair
725
+ * @dev Increments market count, assigns market ID, initializes market metadata
726
+ * @param tokenA Address of the first token in the trading pair
727
+ * @param tokenB Address of the second token in the trading pair
728
+ * @return The newly created market ID
729
+ */
730
+ function createMarket(
731
+ address tokenA,
732
+ address tokenB
733
+ ) internal returns (uint256) {
734
+ marketCount++;
735
+ marketId[tokenA][tokenB] = marketCount;
736
+ marketMetadata[marketCount] = MarketInformation(tokenA, tokenB, 0, 0);
737
+ return marketCount;
738
+ }
739
+
740
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
741
+ // Tools for Evvm
742
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
743
+
744
+ /**
745
+ * @notice Internal function to process payments through EVVM contract
746
+ * @dev Calls EVVM.pay() with all necessary parameters for token transfer
747
+ * @param _user_Evvm Address of the user making the payment
748
+ * @param _token_Evvm Address of the token being transferred
749
+ * @param _nonce_Evvm Nonce for the EVVM transaction
750
+ * @param _ammount_Evvm Amount of tokens to transfer
751
+ * @param _priorityFee_Evvm Additional priority fee for the transaction
752
+ * @param _priority_Evvm Whether to use priority (async) processing
753
+ * @param _signature_Evvm User's signature authorizing the payment
754
+ */
755
+ function makePay(
756
+ address _user_Evvm,
757
+ address _token_Evvm,
758
+ uint256 _nonce_Evvm,
759
+ uint256 _ammount_Evvm,
760
+ uint256 _priorityFee_Evvm,
761
+ bool _priority_Evvm,
762
+ bytes memory _signature_Evvm
763
+ ) internal {
764
+ Evvm(evvmAddress).pay(
765
+ _user_Evvm,
766
+ address(this),
767
+ "",
768
+ _token_Evvm,
769
+ _ammount_Evvm,
770
+ _priorityFee_Evvm,
771
+ _nonce_Evvm,
772
+ _priority_Evvm,
773
+ address(this),
774
+ _signature_Evvm
775
+ );
776
+ }
777
+
778
+ /**
779
+ * @notice Internal function to distribute tokens from contract balance via EVVM
780
+ * @dev Calls EVVM.caPay() to transfer tokens from P2PSwap to specified user
781
+ * @param _user_Evvm Address of the recipient
782
+ * @param _token_Evvm Address of the token to transfer
783
+ * @param _ammount_Evvm Amount of tokens to transfer
784
+ */
785
+ function makeCaPay(
786
+ address _user_Evvm,
787
+ address _token_Evvm,
788
+ uint256 _ammount_Evvm
789
+ ) internal {
790
+ Evvm(evvmAddress).caPay(_user_Evvm, _token_Evvm, _ammount_Evvm);
791
+ }
792
+
793
+ /**
794
+ * @notice Internal function to distribute tokens to multiple recipients via EVVM
795
+ * @dev Calls EVVM.disperseCaPay() for efficient batch token distribution
796
+ * @param toData Array of recipient addresses and amounts
797
+ * @param token Address of the token to distribute
798
+ * @param amount Total amount being distributed (must match sum of individual amounts)
799
+ */
800
+ function makeDisperseCaPay(
801
+ EvvmStructs.DisperseCaPayMetadata[] memory toData,
802
+ address token,
803
+ uint256 amount
804
+ ) internal {
805
+ Evvm(evvmAddress).disperseCaPay(toData, token, amount);
806
+ }
807
+
808
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
809
+ // Admin tools
810
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
811
+
812
+ /**
813
+ * @notice Proposes a new contract owner with 1-day delay
814
+ * @dev Only current owner can propose, starts time-delayed governance process
815
+ * @param _owner Address of the proposed new owner
816
+ */
817
+ function proposeOwner(address _owner) external {
818
+ if (msg.sender != owner) {
819
+ revert();
820
+ }
821
+ owner_proposal = _owner;
822
+ owner_timeToAccept = block.timestamp + 1 days;
823
+ }
824
+
825
+ /**
826
+ * @notice Rejects the current owner change proposal
827
+ * @dev Only proposed owner can reject before deadline expires
828
+ */
829
+ function rejectProposeOwner() external {
830
+ if (
831
+ msg.sender != owner_proposal || block.timestamp > owner_timeToAccept
832
+ ) {
833
+ revert();
834
+ }
835
+ owner_proposal = address(0);
836
+ }
837
+
838
+ /**
839
+ * @notice Accepts ownership transfer after time delay
840
+ * @dev Only proposed owner can accept after 1-day waiting period
841
+ */
842
+ function acceptOwner() external {
843
+ if (
844
+ msg.sender != owner_proposal || block.timestamp > owner_timeToAccept
845
+ ) {
846
+ revert();
847
+ }
848
+ owner = owner_proposal;
849
+ owner_proposal = address(0);
850
+ }
851
+
852
+ /**
853
+ * @notice Proposes new fee distribution percentages for fixed fee model
854
+ * @dev Percentages must sum to 10,000 basis points (100%)
855
+ * @param _seller Percentage for order sellers (basis points)
856
+ * @param _service Percentage for P2PSwap service (basis points)
857
+ * @param _mateStaker Percentage for MATE token stakers (basis points)
858
+ */
859
+ function proposeFillFixedPercentage(
860
+ uint256 _seller,
861
+ uint256 _service,
862
+ uint256 _mateStaker
863
+ ) external {
864
+ if (msg.sender != owner) {
865
+ revert();
866
+ }
867
+ if (_seller + _service + _mateStaker != 10_000) {
868
+ revert();
869
+ }
870
+ rewardPercentage_proposal = Percentage(_seller, _service, _mateStaker);
871
+ rewardPercentage_timeToAcceptNewChange = block.timestamp + 1 days;
872
+ }
873
+
874
+ /**
875
+ * @notice Rejects the current fee percentage proposal for fixed fee model
876
+ * @dev Only owner can reject before deadline expires, resets proposal to zero
877
+ */
878
+ function rejectProposeFillFixedPercentage() external {
879
+ if (
880
+ msg.sender != owner ||
881
+ block.timestamp > rewardPercentage_timeToAcceptNewChange
882
+ ) {
883
+ revert();
884
+ }
885
+ rewardPercentage_proposal = Percentage(0, 0, 0);
886
+ }
887
+
888
+ /**
889
+ * @notice Accepts the fee percentage proposal for fixed fee model after time delay
890
+ * @dev Only owner can accept after 1-day waiting period, applies new percentages
891
+ */
892
+ function acceptFillFixedPercentage() external {
893
+ if (
894
+ msg.sender != owner ||
895
+ block.timestamp > rewardPercentage_timeToAcceptNewChange
896
+ ) {
897
+ revert();
898
+ }
899
+ rewardPercentage = rewardPercentage_proposal;
900
+ }
901
+
902
+ /**
903
+ * @notice Proposes new fee distribution percentages for proportional fee model
904
+ * @dev Percentages must sum to 10,000 basis points (100%)
905
+ * @param _seller Percentage for order sellers (basis points)
906
+ * @param _service Percentage for P2PSwap service (basis points)
907
+ * @param _mateStaker Percentage for MATE token stakers (basis points)
908
+ */
909
+ function proposeFillPropotionalPercentage(
910
+ uint256 _seller,
911
+ uint256 _service,
912
+ uint256 _mateStaker
913
+ ) external {
914
+ if (msg.sender != owner || _seller + _service + _mateStaker != 10_000) {
915
+ revert();
916
+ }
917
+ rewardPercentage_proposal = Percentage(_seller, _service, _mateStaker);
918
+ rewardPercentage_timeToAcceptNewChange = block.timestamp + 1 days;
919
+ }
920
+
921
+ /**
922
+ * @notice Rejects the current fee percentage proposal for proportional fee model
923
+ * @dev Only owner can reject before deadline expires, resets proposal to zero
924
+ */
925
+ function rejectProposeFillPropotionalPercentage() external {
926
+ if (
927
+ msg.sender != owner ||
928
+ block.timestamp > rewardPercentage_timeToAcceptNewChange
929
+ ) {
930
+ revert();
931
+ }
932
+ rewardPercentage_proposal = Percentage(0, 0, 0);
933
+ }
934
+
935
+ /**
936
+ * @notice Accepts the fee percentage proposal for proportional fee model after time delay
937
+ * @dev Only owner can accept after 1-day waiting period, applies new percentages
938
+ */
939
+ function acceptFillPropotionalPercentage() external {
940
+ if (
941
+ msg.sender != owner ||
942
+ block.timestamp > rewardPercentage_timeToAcceptNewChange
943
+ ) {
944
+ revert();
945
+ }
946
+ rewardPercentage = rewardPercentage_proposal;
947
+ }
948
+
949
+ /**
950
+ * @notice Proposes a new percentage fee for proportional fee calculation
951
+ * @dev Only owner can propose, starts time-delayed governance process
952
+ * @param _percentageFee New percentage fee value in basis points
953
+ */
954
+ function proposePercentageFee(uint256 _percentageFee) external {
955
+ if (msg.sender != owner) {
956
+ revert();
957
+ }
958
+ percentageFee_proposal = _percentageFee;
959
+ percentageFee_timeToAccept = block.timestamp + 1 days;
960
+ }
961
+
962
+ /**
963
+ * @notice Rejects the current percentage fee proposal
964
+ * @dev Only owner can reject before deadline expires, resets proposal to zero
965
+ */
966
+ function rejectProposePercentageFee() external {
967
+ if (
968
+ msg.sender != owner || block.timestamp > percentageFee_timeToAccept
969
+ ) {
970
+ revert();
971
+ }
972
+ percentageFee_proposal = 0;
973
+ }
974
+
975
+ /**
976
+ * @notice Accepts the percentage fee proposal after time delay
977
+ * @dev Only owner can accept after 1-day waiting period, applies new fee
978
+ */
979
+ function acceptPercentageFee() external {
980
+ if (
981
+ msg.sender != owner || block.timestamp > percentageFee_timeToAccept
982
+ ) {
983
+ revert();
984
+ }
985
+ percentageFee = percentageFee_proposal;
986
+ }
987
+
988
+ /**
989
+ * @notice Proposes a new maximum limit for fixed fee calculations
990
+ * @dev Only owner can propose, starts time-delayed governance process
991
+ * @param _maxLimitFillFixedFee New maximum limit value for fixed fee calculations
992
+ */
993
+ function proposeMaxLimitFillFixedFee(
994
+ uint256 _maxLimitFillFixedFee
995
+ ) external {
996
+ if (msg.sender != owner) {
997
+ revert();
998
+ }
999
+ maxLimitFillFixedFee_proposal = _maxLimitFillFixedFee;
1000
+ maxLimitFillFixedFee_timeToAccept = block.timestamp + 1 days;
1001
+ }
1002
+
1003
+ /**
1004
+ * @notice Rejects the current maximum limit proposal for fixed fees
1005
+ * @dev Only owner can reject before deadline expires, resets proposal to zero
1006
+ */
1007
+ function rejectProposeMaxLimitFillFixedFee() external {
1008
+ if (
1009
+ msg.sender != owner ||
1010
+ block.timestamp > maxLimitFillFixedFee_timeToAccept
1011
+ ) {
1012
+ revert();
1013
+ }
1014
+ maxLimitFillFixedFee_proposal = 0;
1015
+ }
1016
+
1017
+ /**
1018
+ * @notice Accepts the maximum limit proposal for fixed fees after time delay
1019
+ * @dev Only owner can accept after 1-day waiting period, applies new limit
1020
+ */
1021
+ function acceptMaxLimitFillFixedFee() external {
1022
+ if (
1023
+ msg.sender != owner ||
1024
+ block.timestamp > maxLimitFillFixedFee_timeToAccept
1025
+ ) {
1026
+ revert();
1027
+ }
1028
+ maxLimitFillFixedFee = maxLimitFillFixedFee_proposal;
1029
+ }
1030
+
1031
+ /**
1032
+ * @notice Proposes withdrawal of accumulated service fees
1033
+ * @dev Only owner can propose, amount must not exceed available balance
1034
+ * @param _tokenToWithdraw Address of token to withdraw
1035
+ * @param _amountToWithdraw Amount of tokens to withdraw
1036
+ * @param _to Recipient address for the withdrawal
1037
+ */
1038
+ function proposeWithdrawal(
1039
+ address _tokenToWithdraw,
1040
+ uint256 _amountToWithdraw,
1041
+ address _to
1042
+ ) external {
1043
+ if (
1044
+ msg.sender != owner ||
1045
+ _amountToWithdraw > balancesOfContract[_tokenToWithdraw]
1046
+ ) {
1047
+ revert();
1048
+ }
1049
+ tokenToWithdraw = _tokenToWithdraw;
1050
+ amountToWithdraw = _amountToWithdraw;
1051
+ recipientToWithdraw = _to;
1052
+ timeToWithdrawal = block.timestamp + 1 days;
1053
+ }
1054
+
1055
+ /**
1056
+ * @notice Rejects the current withdrawal proposal
1057
+ * @dev Only owner can reject before deadline expires, clears all withdrawal data
1058
+ */
1059
+ function rejectProposeWithdrawal() external {
1060
+ if (msg.sender != owner || block.timestamp > timeToWithdrawal) {
1061
+ revert();
1062
+ }
1063
+ tokenToWithdraw = address(0);
1064
+ amountToWithdraw = 0;
1065
+ recipientToWithdraw = address(0);
1066
+ timeToWithdrawal = 0;
1067
+ }
1068
+
1069
+ /**
1070
+ * @notice Executes the withdrawal proposal after time delay
1071
+ * @dev Transfers tokens via EVVM, updates balance, and clears withdrawal data
1072
+ */
1073
+ function acceptWithdrawal() external {
1074
+ if (msg.sender != owner || block.timestamp > timeToWithdrawal) {
1075
+ revert();
1076
+ }
1077
+ makeCaPay(recipientToWithdraw, tokenToWithdraw, amountToWithdraw);
1078
+ balancesOfContract[tokenToWithdraw] -= amountToWithdraw;
1079
+
1080
+ tokenToWithdraw = address(0);
1081
+ amountToWithdraw = 0;
1082
+ recipientToWithdraw = address(0);
1083
+ timeToWithdrawal = 0;
1084
+ }
1085
+
1086
+ /**
1087
+ * @notice Stakes accumulated MATE tokens using service staking functionality
1088
+ * @dev Only owner can stake, requires sufficient MATE token balance
1089
+ * @param amount Number of staking tokens to stake (not MATE token amount)
1090
+ */
1091
+ function stake(uint256 amount) external {
1092
+ if (
1093
+ msg.sender != owner ||
1094
+ amount * Staking(stakingAddress).priceOfStaking() >
1095
+ balancesOfContract[0x0000000000000000000000000000000000000001]
1096
+ ) revert();
1097
+
1098
+ _makeStakeService(amount);
1099
+ }
1100
+
1101
+ /**
1102
+ * @notice Unstakes service staking tokens and receives MATE tokens
1103
+ * @dev Only owner can unstake, subject to staking contract time locks
1104
+ * @param amount Number of staking tokens to unstake
1105
+ */
1106
+ function unstake(uint256 amount) external {
1107
+ if (msg.sender != owner) revert();
1108
+
1109
+ _makeUnstakeService(amount);
1110
+ }
1111
+
1112
+ /**
1113
+ * @notice Manually adds balance to the contract for a specific token
1114
+ * @dev Only owner can add balance, useful for reconciling accounting discrepancies
1115
+ * @param _token Address of the token to add balance for
1116
+ * @param _amount Amount to add to the contract's balance tracking
1117
+ */
1118
+ function addBalance(address _token, uint256 _amount) external {
1119
+ if (msg.sender != owner) {
1120
+ revert();
1121
+ }
1122
+ balancesOfContract[_token] += _amount;
1123
+ }
1124
+
1125
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
1126
+ //getters
1127
+ //◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
1128
+ /**
1129
+ * @notice Retrieves all active orders in a specific market
1130
+ * @dev Returns array with extended order information including market and order IDs
1131
+ * @param market The market ID to query orders from
1132
+ * @return orders Array of OrderForGetter structs containing all active orders
1133
+ */
1134
+ function getAllMarketOrders(
1135
+ uint256 market
1136
+ ) public view returns (OrderForGetter[] memory orders) {
1137
+ orders = new OrderForGetter[](marketMetadata[market].maxSlot + 1);
1138
+
1139
+ for (uint256 i = 1; i <= marketMetadata[market].maxSlot + 1; i++) {
1140
+ if (ordersInsideMarket[market][i].seller != address(0)) {
1141
+ orders[i - 1] = OrderForGetter(
1142
+ market,
1143
+ i,
1144
+ ordersInsideMarket[market][i].seller,
1145
+ ordersInsideMarket[market][i].amountA,
1146
+ ordersInsideMarket[market][i].amountB
1147
+ );
1148
+ }
1149
+ }
1150
+ return orders;
1151
+ }
1152
+
1153
+ /**
1154
+ * @notice Retrieves a specific order by market and order ID
1155
+ * @param market The market ID containing the order
1156
+ * @param orderId The specific order ID to retrieve
1157
+ * @return order The Order struct containing seller address and amounts
1158
+ */
1159
+ function getOrder(
1160
+ uint256 market,
1161
+ uint256 orderId
1162
+ ) public view returns (Order memory order) {
1163
+ order = ordersInsideMarket[market][orderId];
1164
+ return order;
1165
+ }
1166
+
1167
+ /**
1168
+ * @notice Retrieves all orders from a specific user in a specific market
1169
+ * @dev Returns array with extended order information for user's orders only
1170
+ * @param user Address of the user whose orders to retrieve
1171
+ * @param market The market ID to query orders from
1172
+ * @return orders Array of OrderForGetter structs containing user's orders in the market
1173
+ */
1174
+ function getMyOrdersInSpecificMarket(
1175
+ address user,
1176
+ uint256 market
1177
+ ) public view returns (OrderForGetter[] memory orders) {
1178
+ orders = new OrderForGetter[](marketMetadata[market].maxSlot + 1);
1179
+
1180
+ for (uint256 i = 1; i <= marketMetadata[market].maxSlot + 1; i++) {
1181
+ if (ordersInsideMarket[market][i].seller == user) {
1182
+ orders[i - 1] = OrderForGetter(
1183
+ market,
1184
+ i,
1185
+ ordersInsideMarket[market][i].seller,
1186
+ ordersInsideMarket[market][i].amountA,
1187
+ ordersInsideMarket[market][i].amountB
1188
+ );
1189
+ }
1190
+ }
1191
+ return orders;
1192
+ }
1193
+
1194
+ /**
1195
+ * @notice Finds the market ID for a specific token pair
1196
+ * @param tokenA Address of the first token
1197
+ * @param tokenB Address of the second token
1198
+ * @return The market ID for the token pair, or 0 if market doesn't exist
1199
+ */
1200
+ function findMarket(
1201
+ address tokenA,
1202
+ address tokenB
1203
+ ) public view returns (uint256) {
1204
+ return marketId[tokenA][tokenB];
1205
+ }
1206
+
1207
+ /**
1208
+ * @notice Retrieves metadata information for a specific market
1209
+ * @param market The market ID to get metadata for
1210
+ * @return MarketInformation struct containing token addresses, max slot, and other metadata
1211
+ */
1212
+ function getMarketMetadata(
1213
+ uint256 market
1214
+ ) public view returns (MarketInformation memory) {
1215
+ return marketMetadata[market];
1216
+ }
1217
+
1218
+ /**
1219
+ * @notice Retrieves metadata information for all existing markets
1220
+ * @dev Returns array of all market metadata from market ID 1 to marketCount
1221
+ * @return Array of MarketInformation structs containing all markets data
1222
+ */
1223
+ function getAllMarketsMetadata()
1224
+ public
1225
+ view
1226
+ returns (MarketInformation[] memory)
1227
+ {
1228
+ MarketInformation[] memory markets = new MarketInformation[](
1229
+ marketCount + 1
1230
+ );
1231
+ for (uint256 i = 1; i <= marketCount; i++) {
1232
+ markets[i - 1] = marketMetadata[i];
1233
+ }
1234
+ return markets;
1235
+ }
1236
+
1237
+ /**
1238
+ * @notice Checks if a nonce has been used by a specific user
1239
+ * @dev Used to prevent replay attacks in P2P swap operations
1240
+ * @param user Address of the user to check
1241
+ * @param nonce The nonce value to verify
1242
+ * @return True if nonce has been used, false otherwise
1243
+ */
1244
+ function checkIfANonceP2PSwapIsUsed(
1245
+ address user,
1246
+ uint256 nonce
1247
+ ) public view returns (bool) {
1248
+ return nonceP2PSwap[user][nonce];
1249
+ }
1250
+
1251
+ /**
1252
+ * @notice Returns the accumulated service fee balance for a specific token
1253
+ * @param token Address of the token to check balance for
1254
+ * @return The accumulated balance of the specified token
1255
+ */
1256
+ function getBalanceOfContract(
1257
+ address token
1258
+ ) external view returns (uint256) {
1259
+ return balancesOfContract[token];
1260
+ }
1261
+
1262
+ /**
1263
+ * @notice Returns the currently proposed new owner address
1264
+ * @return Address of the proposed owner, or address(0) if no proposal exists
1265
+ */
1266
+ function getOwnerProposal() external view returns (address) {
1267
+ return owner_proposal;
1268
+ }
1269
+
1270
+ /**
1271
+ * @notice Returns the current contract owner address
1272
+ * @return Address of the current contract owner
1273
+ */
1274
+ function getOwner() external view returns (address) {
1275
+ return owner;
1276
+ }
1277
+
1278
+ /**
1279
+ * @notice Returns the deadline timestamp for accepting ownership transfer
1280
+ * @return Timestamp until which the ownership proposal can be accepted
1281
+ */
1282
+ function getOwnerTimeToAccept() external view returns (uint256) {
1283
+ return owner_timeToAccept;
1284
+ }
1285
+
1286
+ /**
1287
+ * @notice Returns the currently proposed reward percentage distribution
1288
+ * @return Percentage struct with proposed seller, service, and staker percentages
1289
+ */
1290
+ function getRewardPercentageProposal()
1291
+ external
1292
+ view
1293
+ returns (Percentage memory)
1294
+ {
1295
+ return rewardPercentage_proposal;
1296
+ }
1297
+
1298
+ /**
1299
+ * @notice Returns the current active reward percentage distribution
1300
+ * @return Percentage struct with active seller, service, and staker percentages
1301
+ */
1302
+ function getRewardPercentage() external view returns (Percentage memory) {
1303
+ return rewardPercentage;
1304
+ }
1305
+
1306
+ /**
1307
+ * @notice Returns the currently proposed percentage fee value
1308
+ * @return Proposed percentage fee in basis points for proportional fee calculation
1309
+ */
1310
+ function getProposalPercentageFee() external view returns (uint256) {
1311
+ return percentageFee_proposal;
1312
+ }
1313
+
1314
+ /**
1315
+ * @notice Returns the current active percentage fee value
1316
+ * @return Active percentage fee in basis points for proportional fee calculation
1317
+ */
1318
+ function getPercentageFee() external view returns (uint256) {
1319
+ return percentageFee;
1320
+ }
1321
+
1322
+ /**
1323
+ * @notice Returns the currently proposed maximum limit for fixed fee calculations
1324
+ * @return Proposed maximum limit value for fixed fee model
1325
+ */
1326
+ function getMaxLimitFillFixedFeeProposal() external view returns (uint256) {
1327
+ return maxLimitFillFixedFee_proposal;
1328
+ }
1329
+
1330
+ /**
1331
+ * @notice Returns the current active maximum limit for fixed fee calculations
1332
+ * @return Active maximum limit value for fixed fee model
1333
+ */
1334
+ function getMaxLimitFillFixedFee() external view returns (uint256) {
1335
+ return maxLimitFillFixedFee;
1336
+ }
1337
+
1338
+ /**
1339
+ * @notice Returns complete information about the current withdrawal proposal
1340
+ * @dev Returns all withdrawal parameters including token, amount, recipient, and deadline
1341
+ * @return tokenToWithdraw Address of token to be withdrawn
1342
+ * @return amountToWithdraw Amount of tokens to be withdrawn
1343
+ * @return recipientToWithdraw Address that will receive the tokens
1344
+ * @return timeToWithdrawal Deadline timestamp for accepting the withdrawal
1345
+ */
1346
+ function getProposedWithdrawal()
1347
+ external
1348
+ view
1349
+ returns (address, uint256, address, uint256)
1350
+ {
1351
+ return (
1352
+ tokenToWithdraw,
1353
+ amountToWithdraw,
1354
+ recipientToWithdraw,
1355
+ timeToWithdrawal
1356
+ );
1357
+ }
1358
+ }