@evvm/testnet-contracts 2.2.3 → 3.0.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/LICENSE +145 -118
- package/README.md +162 -39
- package/contracts/core/Core.sol +1394 -0
- package/contracts/core/lib/CoreStorage.sol +171 -0
- package/contracts/nameService/NameService.sol +666 -586
- package/contracts/nameService/lib/IdentityValidation.sol +18 -3
- package/contracts/p2pSwap/P2PSwap.sol +439 -285
- package/contracts/staking/Estimator.sol +128 -40
- package/contracts/staking/Staking.sol +329 -322
- package/contracts/treasury/Treasury.sol +48 -37
- package/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +585 -198
- package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +425 -174
- package/contracts/treasuryTwoChains/lib/PayloadUtils.sol +2 -4
- package/interfaces/{IEvvm.sol → ICore.sol} +67 -29
- package/interfaces/IEstimator.sol +1 -1
- package/interfaces/INameService.sol +58 -52
- package/interfaces/IP2PSwap.sol +18 -17
- package/interfaces/IStaking.sol +22 -17
- package/interfaces/ITreasury.sol +2 -1
- package/interfaces/ITreasuryExternalChainStation.sol +15 -9
- package/interfaces/ITreasuryHostChainStation.sol +14 -11
- package/interfaces/IUserValidator.sol +6 -0
- package/library/Erc191TestBuilder.sol +350 -297
- package/library/EvvmService.sol +38 -27
- package/library/errors/CoreError.sol +116 -0
- package/library/errors/CrossChainTreasuryError.sol +36 -0
- package/library/errors/NameServiceError.sol +79 -0
- package/library/errors/StakingError.sol +79 -0
- package/library/errors/TreasuryError.sol +33 -0
- package/library/primitives/SignatureRecover.sol +33 -0
- package/library/structs/CoreStructs.sol +146 -0
- package/library/structs/ExternalChainStationStructs.sol +92 -0
- package/library/structs/HostChainStationStructs.sol +77 -0
- package/library/structs/NameServiceStructs.sol +47 -0
- package/library/structs/P2PSwapStructs.sol +127 -0
- package/library/structs/StakingStructs.sol +67 -0
- package/library/utils/AdvancedStrings.sol +84 -5
- package/library/utils/CAUtils.sol +29 -0
- package/library/utils/SignatureUtil.sol +34 -0
- package/library/utils/governance/Admin.sol +66 -0
- package/library/utils/governance/ProposalStructs.sol +49 -0
- package/library/utils/service/CoreExecution.sol +177 -0
- package/library/utils/service/StakingServiceUtils.sol +30 -3
- package/library/utils/signature/CoreHashUtils.sol +73 -0
- package/library/utils/signature/NameServiceHashUtils.sol +156 -0
- package/library/utils/signature/P2PSwapHashUtils.sol +65 -0
- package/library/utils/signature/StakingHashUtils.sol +41 -0
- package/library/utils/signature/TreasuryCrossChainHashUtils.sol +40 -0
- package/package.json +2 -1
- package/contracts/evvm/Evvm.sol +0 -1327
- package/contracts/evvm/lib/ErrorsLib.sol +0 -18
- package/contracts/evvm/lib/EvvmStorage.sol +0 -62
- package/contracts/evvm/lib/EvvmStructs.sol +0 -90
- package/contracts/evvm/lib/SignatureUtils.sol +0 -120
- package/contracts/nameService/lib/ErrorsLib.sol +0 -21
- package/contracts/nameService/lib/NameServiceStructs.sol +0 -69
- package/contracts/nameService/lib/SignatureUtils.sol +0 -245
- package/contracts/p2pSwap/lib/P2PSwapStructs.sol +0 -59
- package/contracts/p2pSwap/lib/SignatureUtils.sol +0 -98
- package/contracts/staking/lib/ErrorsLib.sol +0 -22
- package/contracts/staking/lib/SignatureUtils.sol +0 -39
- package/contracts/staking/lib/StakingStructs.sol +0 -94
- package/contracts/treasury/lib/ErrorsLib.sol +0 -11
- package/contracts/treasuryTwoChains/lib/ErrorsLib.sol +0 -48
- package/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +0 -80
- package/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +0 -87
- package/contracts/treasuryTwoChains/lib/SignatureUtils.sol +0 -79
- package/library/utils/GovernanceUtils.sol +0 -81
- package/library/utils/nonces/AsyncNonce.sol +0 -32
- package/library/utils/nonces/SyncNonce.sol +0 -27
- package/library/utils/service/EvvmPayments.sol +0 -79
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
// Full license terms available at: https://www.evvm.org/docs/EVVMNoncommercialLicense
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
P2PSwapHashUtils as Hash
|
|
8
|
+
} from "@evvm/testnet-contracts/library/utils/signature/P2PSwapHashUtils.sol";
|
|
9
|
+
import {
|
|
10
|
+
P2PSwapStructs as Structs
|
|
11
|
+
} from "@evvm/testnet-contracts/library/structs/P2PSwapStructs.sol";
|
|
12
|
+
|
|
13
|
+
import {Staking} from "@evvm/testnet-contracts/contracts/staking/Staking.sol";
|
|
14
|
+
import {EvvmService} from "@evvm/testnet-contracts/library/EvvmService.sol";
|
|
15
|
+
import {CoreStructs} from "@evvm/testnet-contracts/interfaces/ICore.sol";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
AdvancedStrings
|
|
19
|
+
} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
|
|
20
|
+
|
|
5
21
|
/**
|
|
6
22
|
/$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
|
|
7
23
|
| $$__ $$/$$__ $| $$__ $$/$$__ $$
|
|
@@ -15,38 +31,14 @@ pragma solidity ^0.8.0;
|
|
|
15
31
|
| $$
|
|
16
32
|
|__/
|
|
17
33
|
|
|
18
|
-
* @title P2P Swap
|
|
34
|
+
* @title EVVM P2P Swap
|
|
19
35
|
* @author Mate labs
|
|
20
|
-
* @notice Peer-to-peer decentralized exchange for token trading within
|
|
21
|
-
* @dev
|
|
22
|
-
*
|
|
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)
|
|
36
|
+
* @notice Peer-to-peer decentralized exchange for token trading within EVVM.
|
|
37
|
+
* @dev Supports order book-style trading with customizable fee models.
|
|
38
|
+
* Integrates with Core.sol for asset locking and settlements, and Staking.sol for validator rewards.
|
|
37
39
|
*/
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
import {SignatureUtils} from "@evvm/testnet-contracts/contracts/p2pSwap/lib/SignatureUtils.sol";
|
|
41
|
-
import {AdvancedStrings} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
|
|
42
|
-
import {P2PSwapStructs} from "@evvm/testnet-contracts/contracts/p2pSwap/lib/P2PSwapStructs.sol";
|
|
43
|
-
import {EvvmStructs} from "@evvm/testnet-contracts/interfaces/IEvvm.sol";
|
|
44
|
-
import {EvvmService} from "@evvm/testnet-contracts/library/EvvmService.sol";
|
|
45
|
-
|
|
46
|
-
contract P2PSwap is
|
|
47
|
-
EvvmService,
|
|
48
|
-
P2PSwapStructs
|
|
49
|
-
{
|
|
41
|
+
contract P2PSwap is EvvmService, Structs {
|
|
50
42
|
address owner;
|
|
51
43
|
address owner_proposal;
|
|
52
44
|
uint256 owner_timeToAccept;
|
|
@@ -83,12 +75,10 @@ contract P2PSwap is
|
|
|
83
75
|
mapping(address => uint256) balancesOfContract;
|
|
84
76
|
|
|
85
77
|
constructor(
|
|
86
|
-
address
|
|
78
|
+
address _coreAddress,
|
|
87
79
|
address _stakingAddress,
|
|
88
80
|
address _owner
|
|
89
|
-
)
|
|
90
|
-
EvvmService(_evvmAddress, _stakingAddress)
|
|
91
|
-
{
|
|
81
|
+
) EvvmService(_coreAddress, _stakingAddress) {
|
|
92
82
|
owner = _owner;
|
|
93
83
|
maxLimitFillFixedFee = 0.001 ether;
|
|
94
84
|
percentageFee = 500;
|
|
@@ -99,40 +89,49 @@ contract P2PSwap is
|
|
|
99
89
|
});
|
|
100
90
|
}
|
|
101
91
|
|
|
92
|
+
/**
|
|
93
|
+
* @notice Creates a new limit order in a specific trading market.
|
|
94
|
+
* @dev Locks tokenA in Core.sol and opens an order slot.
|
|
95
|
+
* Markets are automatically created for new token pairs.
|
|
96
|
+
* @param user Seller address.
|
|
97
|
+
* @param metadata Order details (tokens, amounts, nonce).
|
|
98
|
+
* @param signature Seller's authorization signature.
|
|
99
|
+
* @param priorityFeePay Optional priority fee for the executor.
|
|
100
|
+
* @param noncePay Nonce for the Core payment (locks tokenA).
|
|
101
|
+
* @param signaturePay Signature for the Core payment.
|
|
102
|
+
* @return market The ID of the market.
|
|
103
|
+
* @return orderId The ID of the order within that market.
|
|
104
|
+
*/
|
|
102
105
|
function makeOrder(
|
|
103
106
|
address user,
|
|
104
107
|
MetadataMakeOrder memory metadata,
|
|
105
108
|
bytes memory signature,
|
|
106
|
-
uint256
|
|
107
|
-
uint256
|
|
108
|
-
|
|
109
|
-
bytes memory _signature_Evvm
|
|
109
|
+
uint256 priorityFeePay,
|
|
110
|
+
uint256 noncePay,
|
|
111
|
+
bytes memory signaturePay
|
|
110
112
|
) external returns (uint256 market, uint256 orderId) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
user,
|
|
115
|
-
metadata.nonce,
|
|
113
|
+
core.validateAndConsumeNonce(
|
|
114
|
+
user,
|
|
115
|
+
Hash.hashDataForMakeOrder(
|
|
116
116
|
metadata.tokenA,
|
|
117
117
|
metadata.tokenB,
|
|
118
118
|
metadata.amountA,
|
|
119
|
-
metadata.amountB
|
|
120
|
-
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
verifyAsyncNonce(user, metadata.nonce);
|
|
119
|
+
metadata.amountB
|
|
120
|
+
),
|
|
121
|
+
address(0),
|
|
122
|
+
metadata.nonce,
|
|
123
|
+
true,
|
|
124
|
+
signature
|
|
125
|
+
);
|
|
127
126
|
|
|
128
127
|
requestPay(
|
|
129
128
|
user,
|
|
130
129
|
metadata.tokenA,
|
|
131
130
|
metadata.amountA,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
priorityFeePay,
|
|
132
|
+
noncePay,
|
|
133
|
+
true,
|
|
134
|
+
signaturePay
|
|
136
135
|
);
|
|
137
136
|
|
|
138
137
|
market = findMarket(metadata.tokenA, metadata.tokenB);
|
|
@@ -163,67 +162,85 @@ contract P2PSwap is
|
|
|
163
162
|
metadata.amountB
|
|
164
163
|
);
|
|
165
164
|
|
|
166
|
-
if (
|
|
167
|
-
if (
|
|
165
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
166
|
+
if (priorityFeePay > 0) {
|
|
168
167
|
// send the executor the priorityFee
|
|
169
|
-
makeCaPay(msg.sender, metadata.tokenA,
|
|
168
|
+
makeCaPay(msg.sender, metadata.tokenA, priorityFeePay);
|
|
170
169
|
}
|
|
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
170
|
}
|
|
181
171
|
|
|
182
|
-
|
|
172
|
+
// send some mate token reward to the executor (independent of the priorityFee the user attached)
|
|
173
|
+
_rewardExecutor(msg.sender, priorityFeePay > 0 ? 3 : 2);
|
|
183
174
|
}
|
|
184
175
|
|
|
176
|
+
/**
|
|
177
|
+
* @notice Cancels existing order and refunds locked tokens
|
|
178
|
+
* @dev Validates ownership, refunds tokenA, deletes order
|
|
179
|
+
*
|
|
180
|
+
* Cancellation Flow:
|
|
181
|
+
* 1. Validates signature via Core.sol
|
|
182
|
+
* 2. Validates user is order owner
|
|
183
|
+
* 3. Processes optional priority fee
|
|
184
|
+
* 4. Refunds locked tokenA to user
|
|
185
|
+
* 5. Deletes order (sets seller to address(0))
|
|
186
|
+
* 6. Rewards staker if applicable
|
|
187
|
+
*
|
|
188
|
+
* Core.sol Integration:
|
|
189
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
190
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
191
|
+
* - Hash includes tokenA, tokenB, orderId
|
|
192
|
+
* - Prevents replay attacks and double cancellation
|
|
193
|
+
*
|
|
194
|
+
* Core.sol Integration:
|
|
195
|
+
* - Refunds tokenA via makeCaPay (order.amountA)
|
|
196
|
+
* - Priority fee via requestPay (if > 0)
|
|
197
|
+
* - Staker reward: 2-3x MATE via _rewardExecutor
|
|
198
|
+
* - makeCaPay handles staker priority fee distribution
|
|
199
|
+
*
|
|
200
|
+
* Security:
|
|
201
|
+
* - Only order owner can cancel
|
|
202
|
+
* - Atomic refund + deletion
|
|
203
|
+
* - Market slot becomes available for reuse
|
|
204
|
+
*
|
|
205
|
+
* @param user Address that owns the order
|
|
206
|
+
* @param metadata Cancel details (tokens, orderId, nonce)
|
|
207
|
+
* @param priorityFeePay Optional priority fee for staker
|
|
208
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
209
|
+
* @param signaturePay Signature for EVVM payment
|
|
210
|
+
*/
|
|
185
211
|
function cancelOrder(
|
|
186
212
|
address user,
|
|
187
213
|
MetadataCancelOrder memory metadata,
|
|
188
|
-
uint256
|
|
189
|
-
uint256
|
|
190
|
-
|
|
191
|
-
bytes memory _signature_Evvm
|
|
214
|
+
uint256 priorityFeePay,
|
|
215
|
+
uint256 noncePay,
|
|
216
|
+
bytes memory signaturePay
|
|
192
217
|
) external {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
user,
|
|
197
|
-
metadata.nonce,
|
|
218
|
+
core.validateAndConsumeNonce(
|
|
219
|
+
user,
|
|
220
|
+
Hash.hashDataForCancelOrder(
|
|
198
221
|
metadata.tokenA,
|
|
199
222
|
metadata.tokenB,
|
|
200
|
-
metadata.orderId
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
223
|
+
metadata.orderId
|
|
224
|
+
),
|
|
225
|
+
metadata.originExecutor,
|
|
226
|
+
metadata.nonce,
|
|
227
|
+
true,
|
|
228
|
+
metadata.signature
|
|
229
|
+
);
|
|
206
230
|
|
|
207
231
|
uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
|
|
208
232
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
market == 0 ||
|
|
213
|
-
ordersInsideMarket[market][metadata.orderId].seller != user
|
|
214
|
-
) {
|
|
215
|
-
revert("Invalid order");
|
|
216
|
-
}
|
|
233
|
+
_validateOrderOwnership(market, metadata.orderId, user);
|
|
217
234
|
|
|
218
|
-
if (
|
|
235
|
+
if (priorityFeePay > 0) {
|
|
219
236
|
requestPay(
|
|
220
237
|
user,
|
|
221
238
|
MATE_TOKEN_ADDRESS,
|
|
222
239
|
0,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
240
|
+
priorityFeePay,
|
|
241
|
+
noncePay,
|
|
242
|
+
true,
|
|
243
|
+
signaturePay
|
|
227
244
|
);
|
|
228
245
|
}
|
|
229
246
|
|
|
@@ -233,62 +250,85 @@ contract P2PSwap is
|
|
|
233
250
|
ordersInsideMarket[market][metadata.orderId].amountA
|
|
234
251
|
);
|
|
235
252
|
|
|
236
|
-
|
|
253
|
+
_clearOrderAndUpdateMarket(market, metadata.orderId);
|
|
237
254
|
|
|
238
|
-
if (
|
|
239
|
-
makeCaPay(
|
|
240
|
-
msg.sender,
|
|
241
|
-
MATE_TOKEN_ADDRESS,
|
|
242
|
-
_priorityFee_Evvm > 0
|
|
243
|
-
? ((evvm.getRewardAmount() * 3) + _priorityFee_Evvm)
|
|
244
|
-
: (evvm.getRewardAmount() * 2)
|
|
245
|
-
);
|
|
255
|
+
if (core.isAddressStaker(msg.sender) && priorityFeePay > 0) {
|
|
256
|
+
makeCaPay(msg.sender, MATE_TOKEN_ADDRESS, priorityFeePay);
|
|
246
257
|
}
|
|
247
|
-
|
|
248
|
-
markAsyncNonceAsUsed(user, metadata.nonce);
|
|
258
|
+
_rewardExecutor(msg.sender, priorityFeePay > 0 ? 3 : 2);
|
|
249
259
|
}
|
|
250
260
|
|
|
261
|
+
/**
|
|
262
|
+
* @notice Fills order using proportional fee model
|
|
263
|
+
* @dev Fee = amountB * percentageFee / 10,000
|
|
264
|
+
*
|
|
265
|
+
* Proportional Fee Execution Flow:
|
|
266
|
+
* 1. Validates signature via Core.sol
|
|
267
|
+
* 2. Validates market and order exist
|
|
268
|
+
* 3. Calculates fee: (amountB * percentageFee) / 10,000
|
|
269
|
+
* 4. Validates amountOfTokenBToFill >= amountB + fee
|
|
270
|
+
* 5. Collects tokenB + fee via Evvm.requestPay
|
|
271
|
+
* 6. Handles overpayment refund if any
|
|
272
|
+
* 7. Distributes payments (seller, service, staker)
|
|
273
|
+
* 8. Transfers tokenA to buyer via Evvm.makeCaPay
|
|
274
|
+
* 9. Rewards staker (4-5x MATE)
|
|
275
|
+
* 10. Deletes order
|
|
276
|
+
*
|
|
277
|
+
* Core.sol Integration:
|
|
278
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
279
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
280
|
+
* - Hash includes tokenA, tokenB, orderId
|
|
281
|
+
* - Prevents double filling
|
|
282
|
+
*
|
|
283
|
+
* Core.sol Integration:
|
|
284
|
+
* - Collects tokenB via requestPay (amountB + fee)
|
|
285
|
+
* - Distributes via makeDisperseCaPay:
|
|
286
|
+
* * Seller: amountB + (fee * seller%)
|
|
287
|
+
* * Staker: priorityFee + (fee * staker%)
|
|
288
|
+
* * Service: fee * service% (accumulated)
|
|
289
|
+
* - Transfers tokenA to buyer via makeCaPay
|
|
290
|
+
* - Staker reward: 4-5x MATE via _rewardExecutor
|
|
291
|
+
*
|
|
292
|
+
* Fee Calculation:
|
|
293
|
+
* - Base: amountB (order requirement)
|
|
294
|
+
* - Fee: (amountB * percentageFee) / 10,000
|
|
295
|
+
* - Total: amountB + fee
|
|
296
|
+
* - Example: 5% fee = 500 / 10,000
|
|
297
|
+
*
|
|
298
|
+
* @param user Address filling the order (buyer)
|
|
299
|
+
* @param metadata Dispatch details (tokens, orderId, amount)
|
|
300
|
+
* @param priorityFeePay Optional priority fee for staker
|
|
301
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
302
|
+
* @param signaturePay Signature for EVVM payment
|
|
303
|
+
*/
|
|
251
304
|
function dispatchOrder_fillPropotionalFee(
|
|
252
305
|
address user,
|
|
253
306
|
MetadataDispatchOrder memory metadata,
|
|
254
|
-
uint256
|
|
255
|
-
uint256
|
|
256
|
-
|
|
257
|
-
bytes memory _signature_Evvm
|
|
307
|
+
uint256 priorityFeePay,
|
|
308
|
+
uint256 noncePay,
|
|
309
|
+
bytes memory signaturePay
|
|
258
310
|
) external {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
user,
|
|
263
|
-
metadata.nonce,
|
|
311
|
+
core.validateAndConsumeNonce(
|
|
312
|
+
user,
|
|
313
|
+
Hash.hashDataForDispatchOrder(
|
|
264
314
|
metadata.tokenA,
|
|
265
315
|
metadata.tokenB,
|
|
266
|
-
metadata.orderId
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
316
|
+
metadata.orderId
|
|
317
|
+
),
|
|
318
|
+
metadata.originExecutor,
|
|
319
|
+
metadata.nonce,
|
|
320
|
+
true,
|
|
321
|
+
metadata.signature
|
|
322
|
+
);
|
|
272
323
|
|
|
273
324
|
uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
|
|
274
325
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
market == 0 ||
|
|
279
|
-
ordersInsideMarket[market][metadata.orderId].seller == address(0)
|
|
280
|
-
) {
|
|
281
|
-
revert("Invalid order");
|
|
282
|
-
}
|
|
326
|
+
Order storage order = _validateMarketAndOrder(market, metadata.orderId);
|
|
283
327
|
|
|
284
|
-
uint256 fee = calculateFillPropotionalFee(
|
|
285
|
-
|
|
286
|
-
);
|
|
328
|
+
uint256 fee = calculateFillPropotionalFee(order.amountB);
|
|
329
|
+
uint256 requiredAmount = order.amountB + fee;
|
|
287
330
|
|
|
288
|
-
if (
|
|
289
|
-
metadata.amountOfTokenBToFill <
|
|
290
|
-
ordersInsideMarket[market][metadata.orderId].amountB + fee
|
|
291
|
-
) {
|
|
331
|
+
if (metadata.amountOfTokenBToFill < requiredAmount) {
|
|
292
332
|
revert("Insuficient amountOfTokenToFill");
|
|
293
333
|
}
|
|
294
334
|
|
|
@@ -296,120 +336,127 @@ contract P2PSwap is
|
|
|
296
336
|
user,
|
|
297
337
|
metadata.tokenB,
|
|
298
338
|
metadata.amountOfTokenBToFill,
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
339
|
+
priorityFeePay,
|
|
340
|
+
noncePay,
|
|
341
|
+
true,
|
|
342
|
+
signaturePay
|
|
303
343
|
);
|
|
304
344
|
|
|
305
345
|
// si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
346
|
+
bool didRefund = _handleOverpaymentRefund(
|
|
347
|
+
user,
|
|
348
|
+
metadata.tokenB,
|
|
349
|
+
metadata.amountOfTokenBToFill,
|
|
350
|
+
requiredAmount
|
|
335
351
|
);
|
|
336
352
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
10_000;
|
|
340
|
-
|
|
341
|
-
makeDisperseCaPay(
|
|
342
|
-
toData,
|
|
353
|
+
// distribute payments to seller and executor
|
|
354
|
+
_distributePayments(
|
|
343
355
|
metadata.tokenB,
|
|
344
|
-
|
|
356
|
+
order.amountB,
|
|
357
|
+
fee,
|
|
358
|
+
order.seller,
|
|
359
|
+
msg.sender,
|
|
360
|
+
priorityFeePay
|
|
345
361
|
);
|
|
346
362
|
|
|
347
363
|
// pay user with token A
|
|
348
|
-
makeCaPay(
|
|
349
|
-
user,
|
|
350
|
-
metadata.tokenA,
|
|
351
|
-
ordersInsideMarket[market][metadata.orderId].amountA
|
|
352
|
-
);
|
|
364
|
+
makeCaPay(user, metadata.tokenA, order.amountA);
|
|
353
365
|
|
|
354
|
-
|
|
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
|
-
}
|
|
366
|
+
_rewardExecutor(msg.sender, didRefund ? 5 : 4);
|
|
364
367
|
|
|
365
|
-
|
|
366
|
-
marketMetadata[market].ordersAvailable--;
|
|
367
|
-
markAsyncNonceAsUsed(user, metadata.nonce);
|
|
368
|
+
_clearOrderAndUpdateMarket(market, metadata.orderId);
|
|
368
369
|
}
|
|
369
370
|
|
|
371
|
+
/**
|
|
372
|
+
* @notice Fills order using fixed/capped fee model
|
|
373
|
+
* @dev Fee = min(proportionalFee, maxLimitFillFixedFee)
|
|
374
|
+
* with -10% tolerance
|
|
375
|
+
*
|
|
376
|
+
* Fixed Fee Execution Flow:
|
|
377
|
+
* 1. Validates signature via Core.sol
|
|
378
|
+
* 2. Validates market and order exist
|
|
379
|
+
* 3. Calculates capped fee and 10% tolerance
|
|
380
|
+
* 4. Validates amountOfTokenBToFill >= amountB + fee - 10%
|
|
381
|
+
* 5. Collects tokenB + amount via Evvm.requestPay
|
|
382
|
+
* 6. Calculates final fee based on actual payment
|
|
383
|
+
* 7. Handles overpayment refund if any
|
|
384
|
+
* 8. Distributes payments (seller, service, staker)
|
|
385
|
+
* 9. Transfers tokenA to buyer via Evvm.makeCaPay
|
|
386
|
+
* 10. Rewards staker (4-5x MATE)
|
|
387
|
+
* 11. Deletes order
|
|
388
|
+
*
|
|
389
|
+
* Core.sol Integration:
|
|
390
|
+
* - Validates signature with State.validateAndConsumeNonce
|
|
391
|
+
* - Uses async nonce (isAsyncExec = true)
|
|
392
|
+
* - Hash includes tokenA, tokenB, orderId
|
|
393
|
+
* - Prevents double filling
|
|
394
|
+
*
|
|
395
|
+
* Core.sol Integration:
|
|
396
|
+
* - Collects tokenB via requestPay (variable amount)
|
|
397
|
+
* - Distributes via makeDisperseCaPay:
|
|
398
|
+
* * Seller: amountB + (finalFee * seller%)
|
|
399
|
+
* * Staker: priorityFee + (finalFee * staker%)
|
|
400
|
+
* * Service: finalFee * service% (accumulated)
|
|
401
|
+
* - Transfers tokenA to buyer via makeCaPay
|
|
402
|
+
* - Staker reward: 4-5x MATE via _rewardExecutor
|
|
403
|
+
*
|
|
404
|
+
* Fee Calculation:
|
|
405
|
+
* - Base: amountB (order requirement)
|
|
406
|
+
* - ProportionalFee: (amountB * percentageFee) / 10,000
|
|
407
|
+
* - Fee: min(proportionalFee, maxLimitFillFixedFee)
|
|
408
|
+
* - Tolerance: fee * 10% (fee10)
|
|
409
|
+
* - MinRequired: amountB + fee - fee10
|
|
410
|
+
* - FullRequired: amountB + fee
|
|
411
|
+
* - FinalFee: Based on actual payment amount
|
|
412
|
+
*
|
|
413
|
+
* Tolerance Range:
|
|
414
|
+
* - Accepts payment between [amountB + 90% fee] and
|
|
415
|
+
* [amountB + 100% fee]
|
|
416
|
+
* - Calculates actual fee from payment received
|
|
417
|
+
* - Enables flexible fee payment for users
|
|
418
|
+
*
|
|
419
|
+
* @param user Address filling the order (buyer)
|
|
420
|
+
* @param metadata Dispatch details (tokens, orderId, amount)
|
|
421
|
+
* @param priorityFeePay Optional priority fee for staker
|
|
422
|
+
* @param noncePay Nonce for EVVM payment transaction
|
|
423
|
+
* @param signaturePay Signature for EVVM payment
|
|
424
|
+
* @param maxFillFixedFee Max fee cap (for testing)
|
|
425
|
+
*/
|
|
370
426
|
function dispatchOrder_fillFixedFee(
|
|
371
427
|
address user,
|
|
372
428
|
MetadataDispatchOrder memory metadata,
|
|
373
|
-
uint256
|
|
374
|
-
uint256
|
|
375
|
-
|
|
376
|
-
bytes memory _signature_Evvm,
|
|
429
|
+
uint256 priorityFeePay,
|
|
430
|
+
uint256 noncePay,
|
|
431
|
+
bytes memory signaturePay,
|
|
377
432
|
uint256 maxFillFixedFee ///@dev for testing purposes
|
|
378
433
|
) external {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
user,
|
|
383
|
-
metadata.nonce,
|
|
434
|
+
core.validateAndConsumeNonce(
|
|
435
|
+
user,
|
|
436
|
+
Hash.hashDataForDispatchOrder(
|
|
384
437
|
metadata.tokenA,
|
|
385
438
|
metadata.tokenB,
|
|
386
|
-
metadata.orderId
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
439
|
+
metadata.orderId
|
|
440
|
+
),
|
|
441
|
+
metadata.originExecutor,
|
|
442
|
+
metadata.nonce,
|
|
443
|
+
true,
|
|
444
|
+
metadata.signature
|
|
445
|
+
);
|
|
392
446
|
|
|
393
447
|
uint256 market = findMarket(metadata.tokenA, metadata.tokenB);
|
|
394
448
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (
|
|
398
|
-
market == 0 ||
|
|
399
|
-
ordersInsideMarket[market][metadata.orderId].seller == address(0)
|
|
400
|
-
) {
|
|
401
|
-
revert("Invalid order");
|
|
402
|
-
}
|
|
449
|
+
Order storage order = _validateMarketAndOrder(market, metadata.orderId);
|
|
403
450
|
|
|
404
451
|
(uint256 fee, uint256 fee10) = calculateFillFixedFee(
|
|
405
|
-
|
|
452
|
+
order.amountB,
|
|
406
453
|
maxFillFixedFee
|
|
407
454
|
);
|
|
408
455
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
) {
|
|
456
|
+
uint256 minRequired = order.amountB + fee - fee10;
|
|
457
|
+
uint256 fullRequired = order.amountB + fee;
|
|
458
|
+
|
|
459
|
+
if (metadata.amountOfTokenBToFill < minRequired) {
|
|
413
460
|
revert("Insuficient amountOfTokenBToFill");
|
|
414
461
|
}
|
|
415
462
|
|
|
@@ -417,82 +464,44 @@ contract P2PSwap is
|
|
|
417
464
|
user,
|
|
418
465
|
metadata.tokenB,
|
|
419
466
|
metadata.amountOfTokenBToFill,
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
467
|
+
priorityFeePay,
|
|
468
|
+
noncePay,
|
|
469
|
+
true,
|
|
470
|
+
signaturePay
|
|
424
471
|
);
|
|
425
472
|
|
|
426
|
-
uint256 finalFee =
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
? metadata.amountOfTokenBToFill -
|
|
433
|
-
ordersInsideMarket[market][metadata.orderId].amountB
|
|
434
|
-
: fee;
|
|
473
|
+
uint256 finalFee = _calculateFinalFee(
|
|
474
|
+
metadata.amountOfTokenBToFill,
|
|
475
|
+
order.amountB,
|
|
476
|
+
fee,
|
|
477
|
+
fee10
|
|
478
|
+
);
|
|
435
479
|
|
|
436
480
|
// si es mas del fee + el monto de la orden hacemos caPay al usuario del sobranate
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
|
481
|
+
bool didRefund = _handleOverpaymentRefund(
|
|
482
|
+
user,
|
|
483
|
+
metadata.tokenB,
|
|
484
|
+
metadata.amountOfTokenBToFill,
|
|
485
|
+
fullRequired
|
|
461
486
|
);
|
|
462
487
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
10_000;
|
|
466
|
-
|
|
467
|
-
makeDisperseCaPay(
|
|
468
|
-
toData,
|
|
488
|
+
// distribute payments to seller and executor
|
|
489
|
+
_distributePayments(
|
|
469
490
|
metadata.tokenB,
|
|
470
|
-
|
|
491
|
+
order.amountB,
|
|
492
|
+
finalFee,
|
|
493
|
+
order.seller,
|
|
494
|
+
msg.sender,
|
|
495
|
+
priorityFeePay
|
|
471
496
|
);
|
|
472
497
|
|
|
473
|
-
makeCaPay(
|
|
474
|
-
user,
|
|
475
|
-
metadata.tokenA,
|
|
476
|
-
ordersInsideMarket[market][metadata.orderId].amountA
|
|
477
|
-
);
|
|
498
|
+
makeCaPay(user, metadata.tokenA, order.amountA);
|
|
478
499
|
|
|
479
|
-
|
|
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
|
-
}
|
|
500
|
+
_rewardExecutor(msg.sender, didRefund ? 5 : 4);
|
|
489
501
|
|
|
490
|
-
|
|
491
|
-
marketMetadata[market].ordersAvailable--;
|
|
492
|
-
markAsyncNonceAsUsed(user, metadata.nonce);
|
|
502
|
+
_clearOrderAndUpdateMarket(market, metadata.orderId);
|
|
493
503
|
}
|
|
494
504
|
|
|
495
|
-
//devolver el 0.05% del monto de la orden
|
|
496
505
|
function calculateFillPropotionalFee(
|
|
497
506
|
uint256 amount
|
|
498
507
|
) internal view returns (uint256 fee) {
|
|
@@ -512,6 +521,151 @@ contract P2PSwap is
|
|
|
512
521
|
}
|
|
513
522
|
}
|
|
514
523
|
|
|
524
|
+
/**
|
|
525
|
+
* @dev Calculates the final fee for fixed fee dispatch considering tolerance range
|
|
526
|
+
* @param amountPaid Amount paid by user
|
|
527
|
+
* @param orderAmount Base order amount
|
|
528
|
+
* @param fee Full fee amount
|
|
529
|
+
* @param fee10 10% tolerance of fee
|
|
530
|
+
* @return finalFee The calculated final fee
|
|
531
|
+
*/
|
|
532
|
+
function _calculateFinalFee(
|
|
533
|
+
uint256 amountPaid,
|
|
534
|
+
uint256 orderAmount,
|
|
535
|
+
uint256 fee,
|
|
536
|
+
uint256 fee10
|
|
537
|
+
) internal pure returns (uint256 finalFee) {
|
|
538
|
+
uint256 minRequired = orderAmount + fee - fee10;
|
|
539
|
+
uint256 fullRequired = orderAmount + fee;
|
|
540
|
+
|
|
541
|
+
if (amountPaid >= minRequired && amountPaid < fullRequired) {
|
|
542
|
+
finalFee = amountPaid - orderAmount;
|
|
543
|
+
} else {
|
|
544
|
+
finalFee = fee;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
//◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
|
|
549
|
+
// Internal helper functions to avoid Stack too deep
|
|
550
|
+
//◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* @dev Validates that a market and order exist and are valid
|
|
554
|
+
* @param market The market ID
|
|
555
|
+
* @param orderId The order ID within the market
|
|
556
|
+
* @return order The order data if valid
|
|
557
|
+
*/
|
|
558
|
+
function _validateMarketAndOrder(
|
|
559
|
+
uint256 market,
|
|
560
|
+
uint256 orderId
|
|
561
|
+
) internal view returns (Order storage order) {
|
|
562
|
+
if (market == 0) {
|
|
563
|
+
revert("Invalid order");
|
|
564
|
+
}
|
|
565
|
+
order = ordersInsideMarket[market][orderId];
|
|
566
|
+
if (order.seller == address(0)) {
|
|
567
|
+
revert("Invalid order");
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* @dev Validates that a market exists and the user is the seller of the order
|
|
573
|
+
* @param market The market ID
|
|
574
|
+
* @param orderId The order ID
|
|
575
|
+
* @param user The expected seller address
|
|
576
|
+
*/
|
|
577
|
+
function _validateOrderOwnership(
|
|
578
|
+
uint256 market,
|
|
579
|
+
uint256 orderId,
|
|
580
|
+
address user
|
|
581
|
+
) internal view {
|
|
582
|
+
if (market == 0 || ordersInsideMarket[market][orderId].seller != user) {
|
|
583
|
+
revert("Invalid order");
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* @dev Rewards the executor (staker) with MATE tokens based on operation complexity
|
|
589
|
+
* @param executor The address of the executor
|
|
590
|
+
* @param multiplier The reward multiplier (2, 3, 4, or 5)
|
|
591
|
+
*/
|
|
592
|
+
function _rewardExecutor(address executor, uint256 multiplier) internal {
|
|
593
|
+
if (core.isAddressStaker(executor)) {
|
|
594
|
+
makeCaPay(
|
|
595
|
+
executor,
|
|
596
|
+
MATE_TOKEN_ADDRESS,
|
|
597
|
+
core.getRewardAmount() * multiplier
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* @dev Clears an order and updates market metadata
|
|
604
|
+
* @param market The market ID
|
|
605
|
+
* @param orderId The order ID to clear
|
|
606
|
+
*/
|
|
607
|
+
function _clearOrderAndUpdateMarket(
|
|
608
|
+
uint256 market,
|
|
609
|
+
uint256 orderId
|
|
610
|
+
) internal {
|
|
611
|
+
ordersInsideMarket[market][orderId].seller = address(0);
|
|
612
|
+
marketMetadata[market].ordersAvailable--;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @dev Handles refund to user if they overpaid
|
|
617
|
+
* @param user The user address to refund
|
|
618
|
+
* @param token The token address
|
|
619
|
+
* @param amountPaid The amount the user paid
|
|
620
|
+
* @param amountRequired The required amount (order amount + fee)
|
|
621
|
+
* @return didRefund Whether a refund was made
|
|
622
|
+
*/
|
|
623
|
+
function _handleOverpaymentRefund(
|
|
624
|
+
address user,
|
|
625
|
+
address token,
|
|
626
|
+
uint256 amountPaid,
|
|
627
|
+
uint256 amountRequired
|
|
628
|
+
) internal returns (bool didRefund) {
|
|
629
|
+
if (amountPaid > amountRequired) {
|
|
630
|
+
makeCaPay(user, token, amountPaid - amountRequired);
|
|
631
|
+
return true;
|
|
632
|
+
}
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* @dev Distributes payment to seller and executor, and accumulates service fee
|
|
638
|
+
* @param token The token address for payment
|
|
639
|
+
* @param orderAmount The base order amount
|
|
640
|
+
* @param fee The fee amount to distribute
|
|
641
|
+
* @param seller The seller address
|
|
642
|
+
* @param executor The executor address
|
|
643
|
+
* @param priorityFee The priority fee for executor
|
|
644
|
+
*/
|
|
645
|
+
function _distributePayments(
|
|
646
|
+
address token,
|
|
647
|
+
uint256 orderAmount,
|
|
648
|
+
uint256 fee,
|
|
649
|
+
address seller,
|
|
650
|
+
address executor,
|
|
651
|
+
uint256 priorityFee
|
|
652
|
+
) internal {
|
|
653
|
+
uint256 sellerAmount = orderAmount +
|
|
654
|
+
((fee * rewardPercentage.seller) / 10_000);
|
|
655
|
+
uint256 executorAmount = priorityFee +
|
|
656
|
+
((fee * rewardPercentage.mateStaker) / 10_000);
|
|
657
|
+
|
|
658
|
+
CoreStructs.DisperseCaPayMetadata[]
|
|
659
|
+
memory toData = new CoreStructs.DisperseCaPayMetadata[](2);
|
|
660
|
+
|
|
661
|
+
toData[0] = CoreStructs.DisperseCaPayMetadata(sellerAmount, seller);
|
|
662
|
+
toData[1] = CoreStructs.DisperseCaPayMetadata(executorAmount, executor);
|
|
663
|
+
|
|
664
|
+
balancesOfContract[token] += (fee * rewardPercentage.service) / 10_000;
|
|
665
|
+
|
|
666
|
+
makeDisperseCaPay(toData, token, sellerAmount + executorAmount);
|
|
667
|
+
}
|
|
668
|
+
|
|
515
669
|
function createMarket(
|
|
516
670
|
address tokenA,
|
|
517
671
|
address tokenB
|