@@ -10,7 +10,7 @@ pragma solidity 0.8.18;
10
10
import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitrableV2.sol " ;
11
11
import "../interfaces/IDisputeTemplateRegistry.sol " ;
12
12
13
- /// @title Escrow
13
+ /// @title Escrow for a sale paid in ETH and no fees.
14
14
/// @dev MultipleArbitrableTransaction contract that is compatible with V2.
15
15
/// Adapted from https://github.com/kleros/kleros-interaction/blob/master/contracts/standard/arbitration/MultipleArbitrableTransaction.sol
16
16
contract Escrow is IArbitrableV2 {
@@ -20,34 +20,34 @@ contract Escrow is IArbitrableV2 {
20
20
21
21
enum Party {
22
22
None,
23
- Sender,
24
- Receiver
23
+ Buyer, // Makes a purchase in ETH.
24
+ Seller // Provides a good or service in exchange for ETH.
25
25
}
26
26
27
27
enum Status {
28
28
NoDispute,
29
- WaitingSender ,
30
- WaitingReceiver ,
29
+ WaitingBuyer ,
30
+ WaitingSeller ,
31
31
DisputeCreated,
32
32
TransactionResolved
33
33
}
34
34
35
35
enum Resolution {
36
36
TransactionExecuted,
37
- TimeoutBySender ,
38
- TimeoutByReceiver ,
37
+ TimeoutByBuyer ,
38
+ TimeoutBySeller ,
39
39
RulingEnforced
40
40
}
41
41
42
42
struct Transaction {
43
- address payable sender ;
44
- address payable receiver ;
43
+ address payable buyer ;
44
+ address payable seller ;
45
45
uint256 amount;
46
46
uint256 deadline; // Timestamp at which the transaction can be automatically executed if not disputed.
47
47
uint256 disputeID; // If dispute exists, the ID of the dispute.
48
- uint256 senderFee ; // Total fees paid by the sender .
49
- uint256 receiverFee ; // Total fees paid by the receiver .
50
- uint256 lastInteraction ; // Last interaction for the dispute procedure .
48
+ uint256 buyerFee ; // Total fees paid by the buyer .
49
+ uint256 sellerFee ; // Total fees paid by the seller .
50
+ uint256 lastFeePaymentTime ; // Last time the dispute fees were paid by either party .
51
51
string templateData;
52
52
string templateDataMappings;
53
53
Status status;
@@ -84,13 +84,13 @@ contract Escrow is IArbitrableV2 {
84
84
85
85
/// @dev Emitted when a transaction is created.
86
86
/// @param _transactionID The index of the transaction.
87
- /// @param _sender The address of the sender .
88
- /// @param _receiver The address of the receiver .
87
+ /// @param _buyer The address of the buyer .
88
+ /// @param _seller The address of the seller .
89
89
/// @param _amount The initial amount in the transaction.
90
90
event TransactionCreated (
91
91
uint256 indexed _transactionID ,
92
- address indexed _sender ,
93
- address indexed _receiver ,
92
+ address indexed _buyer ,
93
+ address indexed _seller ,
94
94
uint256 _amount
95
95
);
96
96
@@ -166,152 +166,152 @@ contract Escrow is IArbitrableV2 {
166
166
167
167
/// @dev Create a transaction.
168
168
/// @param _timeoutPayment Time after which a party can automatically execute the arbitrable transaction.
169
- /// @param _receiver The recipient of the transaction.
169
+ /// @param _seller The recipient of the transaction.
170
170
/// @param _templateData The dispute template data.
171
171
/// @param _templateDataMappings The dispute template data mappings.
172
172
/// @return transactionID The index of the transaction.
173
173
function createTransaction (
174
174
uint256 _timeoutPayment ,
175
- address payable _receiver ,
175
+ address payable _seller ,
176
176
string memory _templateData ,
177
177
string memory _templateDataMappings
178
178
) external payable returns (uint256 transactionID ) {
179
179
Transaction storage transaction = transactions.push ();
180
- transaction.sender = payable (msg .sender );
181
- transaction.receiver = _receiver ;
180
+ transaction.buyer = payable (msg .sender );
181
+ transaction.seller = _seller ;
182
182
transaction.amount = msg .value ;
183
183
transaction.deadline = block .timestamp + _timeoutPayment;
184
184
transaction.templateData = _templateData;
185
185
transaction.templateDataMappings = _templateDataMappings;
186
186
187
187
transactionID = transactions.length - 1 ;
188
188
189
- emit TransactionCreated (transactionID, msg .sender , _receiver , msg .value );
189
+ emit TransactionCreated (transactionID, msg .sender , _seller , msg .value );
190
190
}
191
191
192
- /// @dev Pay receiver . To be called if the good or service is provided.
192
+ /// @dev Pay seller . To be called if the good or service is provided.
193
193
/// @param _transactionID The index of the transaction.
194
194
/// @param _amount Amount to pay in wei.
195
195
function pay (uint256 _transactionID , uint256 _amount ) external {
196
196
Transaction storage transaction = transactions[_transactionID];
197
- if (transaction.sender != msg .sender ) revert SenderOnly ();
197
+ if (transaction.buyer != msg .sender ) revert BuyerOnly ();
198
198
if (transaction.status != Status.NoDispute) revert TransactionDisputed ();
199
199
if (_amount > transaction.amount) revert MaximumPaymentAmountExceeded ();
200
200
201
- transaction.receiver .send (_amount); // It is the user responsibility to accept ETH.
201
+ transaction.seller .send (_amount); // It is the user responsibility to accept ETH.
202
202
transaction.amount -= _amount;
203
203
204
204
emit Payment (_transactionID, _amount, msg .sender );
205
205
}
206
206
207
- /// @dev Reimburse sender . To be called if the good or service can't be fully provided.
207
+ /// @dev Reimburse buyer . To be called if the good or service can't be fully provided.
208
208
/// @param _transactionID The index of the transaction.
209
209
/// @param _amountReimbursed Amount to reimburse in wei.
210
210
function reimburse (uint256 _transactionID , uint256 _amountReimbursed ) external {
211
211
Transaction storage transaction = transactions[_transactionID];
212
- if (transaction.receiver != msg .sender ) revert ReceiverOnly ();
212
+ if (transaction.seller != msg .sender ) revert SellerOnly ();
213
213
if (transaction.status != Status.NoDispute) revert TransactionDisputed ();
214
214
if (_amountReimbursed > transaction.amount) revert MaximumPaymentAmountExceeded ();
215
215
216
- transaction.sender .send (_amountReimbursed); // It is the user responsibility to accept ETH.
216
+ transaction.buyer .send (_amountReimbursed); // It is the user responsibility to accept ETH.
217
217
transaction.amount -= _amountReimbursed;
218
218
219
219
emit Payment (_transactionID, _amountReimbursed, msg .sender );
220
220
}
221
221
222
- /// @dev Transfer the transaction's amount to the receiver if the timeout has passed.
222
+ /// @dev Transfer the transaction's amount to the seller if the timeout has passed.
223
223
/// @param _transactionID The index of the transaction.
224
224
function executeTransaction (uint256 _transactionID ) external {
225
225
Transaction storage transaction = transactions[_transactionID];
226
226
if (block .timestamp < transaction.deadline) revert DeadlineNotPassed ();
227
227
if (transaction.status != Status.NoDispute) revert TransactionDisputed ();
228
228
229
- transaction.receiver .send (transaction.amount); // It is the user responsibility to accept ETH.
229
+ transaction.seller .send (transaction.amount); // It is the user responsibility to accept ETH.
230
230
transaction.amount = 0 ;
231
231
transaction.status = Status.TransactionResolved;
232
232
233
233
emit TransactionResolved (_transactionID, Resolution.TransactionExecuted);
234
234
}
235
235
236
- /// @dev Pay the arbitration fee to raise a dispute. To be called by the sender .
236
+ /// @dev Pay the arbitration fee to raise a dispute. To be called by the buyer .
237
237
/// Note that the arbitrator can have createDispute throw, which will make
238
238
/// this function throw and therefore lead to a party being timed-out.
239
239
/// This is not a vulnerability as the arbitrator can rule in favor of one party anyway.
240
240
/// @param _transactionID The index of the transaction.
241
- function payArbitrationFeeBySender (uint256 _transactionID ) external payable {
241
+ function payArbitrationFeeByBuyer (uint256 _transactionID ) external payable {
242
242
Transaction storage transaction = transactions[_transactionID];
243
243
if (transaction.status >= Status.DisputeCreated) revert DisputeAlreadyCreatedOrTransactionAlreadyExecuted ();
244
- if (msg .sender != transaction.sender ) revert SenderOnly ();
244
+ if (msg .sender != transaction.buyer ) revert BuyerOnly ();
245
245
246
- transaction.senderFee += msg .value ;
246
+ transaction.buyerFee += msg .value ;
247
247
uint256 arbitrationCost = arbitrator.arbitrationCost (arbitratorExtraData);
248
- if (transaction.senderFee < arbitrationCost) revert SenderFeeNotCoverArbitrationCosts ();
248
+ if (transaction.buyerFee < arbitrationCost) revert BuyerFeeNotCoverArbitrationCosts ();
249
249
250
- transaction.lastInteraction = block .timestamp ;
250
+ transaction.lastFeePaymentTime = block .timestamp ;
251
251
252
- if (transaction.receiverFee < arbitrationCost) {
253
- // The receiver still has to pay. This can also happen if he has paid, but arbitrationCost has increased.
254
- transaction.status = Status.WaitingReceiver ;
255
- emit HasToPayFee (_transactionID, Party.Receiver );
252
+ if (transaction.sellerFee < arbitrationCost) {
253
+ // The seller still has to pay. This can also happen if he has paid, but arbitrationCost has increased.
254
+ transaction.status = Status.WaitingSeller ;
255
+ emit HasToPayFee (_transactionID, Party.Seller );
256
256
} else {
257
- // The receiver has also paid the fee. We create the dispute.
257
+ // The seller has also paid the fee. We create the dispute.
258
258
raiseDispute (_transactionID, arbitrationCost);
259
259
}
260
260
}
261
261
262
- /// @dev Pay the arbitration fee to raise a dispute. To be called by the receiver .
263
- /// Note that this function mirrors payArbitrationFeeBySender .
262
+ /// @dev Pay the arbitration fee to raise a dispute. To be called by the seller .
263
+ /// Note that this function mirrors payArbitrationFeeByBuyer .
264
264
/// @param _transactionID The index of the transaction.
265
- function payArbitrationFeeByReceiver (uint256 _transactionID ) external payable {
265
+ function payArbitrationFeeBySeller (uint256 _transactionID ) external payable {
266
266
Transaction storage transaction = transactions[_transactionID];
267
267
if (transaction.status >= Status.DisputeCreated) revert DisputeAlreadyCreatedOrTransactionAlreadyExecuted ();
268
- if (msg .sender != transaction.receiver ) revert ReceiverOnly ();
268
+ if (msg .sender != transaction.seller ) revert SellerOnly ();
269
269
270
- transaction.receiverFee += msg .value ;
270
+ transaction.sellerFee += msg .value ;
271
271
uint256 arbitrationCost = arbitrator.arbitrationCost (arbitratorExtraData);
272
- if (transaction.receiverFee < arbitrationCost) revert ReceiverFeeNotCoverArbitrationCosts ();
272
+ if (transaction.sellerFee < arbitrationCost) revert SellerFeeNotCoverArbitrationCosts ();
273
273
274
- transaction.lastInteraction = block .timestamp ;
274
+ transaction.lastFeePaymentTime = block .timestamp ;
275
275
276
- if (transaction.senderFee < arbitrationCost) {
277
- // The sender still has to pay. This can also happen if he has paid, but arbitrationCost has increased.
278
- transaction.status = Status.WaitingSender ;
279
- emit HasToPayFee (_transactionID, Party.Sender );
276
+ if (transaction.buyerFee < arbitrationCost) {
277
+ // The buyer still has to pay. This can also happen if he has paid, but arbitrationCost has increased.
278
+ transaction.status = Status.WaitingBuyer ;
279
+ emit HasToPayFee (_transactionID, Party.Buyer );
280
280
} else {
281
- // The sender has also paid the fee. We create the dispute.
281
+ // The buyer has also paid the fee. We create the dispute.
282
282
raiseDispute (_transactionID, arbitrationCost);
283
283
}
284
284
}
285
285
286
- /// @dev Reimburse sender if receiver fails to pay the fee.
286
+ /// @dev Reimburse buyer if seller fails to pay the fee.
287
287
/// @param _transactionID The index of the transaction.
288
- function timeOutBySender (uint256 _transactionID ) external {
288
+ function timeOutByBuyer (uint256 _transactionID ) external {
289
289
Transaction storage transaction = transactions[_transactionID];
290
- if (transaction.status != Status.WaitingReceiver ) revert NotWaitingForReceiverFees ();
291
- if (block .timestamp - transaction.lastInteraction < feeTimeout) revert TimeoutNotPassed ();
290
+ if (transaction.status != Status.WaitingSeller ) revert NotWaitingForSellerFees ();
291
+ if (block .timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed ();
292
292
293
- if (transaction.receiverFee != 0 ) {
294
- transaction.receiver .send (transaction.receiverFee ); // It is the user responsibility to accept ETH.
295
- transaction.receiverFee = 0 ;
293
+ if (transaction.sellerFee != 0 ) {
294
+ transaction.seller .send (transaction.sellerFee ); // It is the user responsibility to accept ETH.
295
+ transaction.sellerFee = 0 ;
296
296
}
297
- executeRuling (_transactionID, uint256 (Party.Sender ));
298
- emit TransactionResolved (_transactionID, Resolution.TimeoutBySender );
297
+ executeRuling (_transactionID, uint256 (Party.Buyer ));
298
+ emit TransactionResolved (_transactionID, Resolution.TimeoutByBuyer );
299
299
}
300
300
301
- /// @dev Pay receiver if sender fails to pay the fee.
301
+ /// @dev Pay seller if buyer fails to pay the fee.
302
302
/// @param _transactionID The index of the transaction.
303
- function timeOutByReceiver (uint256 _transactionID ) external {
303
+ function timeOutBySeller (uint256 _transactionID ) external {
304
304
Transaction storage transaction = transactions[_transactionID];
305
- if (transaction.status != Status.WaitingSender ) revert NotWaitingForSenderFees ();
306
- if (block .timestamp - transaction.lastInteraction < feeTimeout) revert TimeoutNotPassed ();
305
+ if (transaction.status != Status.WaitingBuyer ) revert NotWaitingForBuyerFees ();
306
+ if (block .timestamp - transaction.lastFeePaymentTime < feeTimeout) revert TimeoutNotPassed ();
307
307
308
- if (transaction.senderFee != 0 ) {
309
- transaction.sender .send (transaction.senderFee ); // It is the user responsibility to accept ETH.
310
- transaction.senderFee = 0 ;
308
+ if (transaction.buyerFee != 0 ) {
309
+ transaction.buyer .send (transaction.buyerFee ); // It is the user responsibility to accept ETH.
310
+ transaction.buyerFee = 0 ;
311
311
}
312
312
313
- executeRuling (_transactionID, uint256 (Party.Receiver ));
314
- emit TransactionResolved (_transactionID, Resolution.TimeoutByReceiver );
313
+ executeRuling (_transactionID, uint256 (Party.Seller ));
314
+ emit TransactionResolved (_transactionID, Resolution.TimeoutBySeller );
315
315
}
316
316
317
317
/// @dev Give a ruling for a dispute. Must be called by the arbitrator to enforce the final ruling.
@@ -348,41 +348,41 @@ contract Escrow is IArbitrableV2 {
348
348
disputeIDtoTransactionID[transaction.disputeID] = _transactionID;
349
349
emit DisputeRequest (arbitrator, transaction.disputeID, _transactionID, templateId, "" );
350
350
351
- // Refund sender if he overpaid.
352
- if (transaction.senderFee > _arbitrationCost) {
353
- uint256 extraFeeSender = transaction.senderFee - _arbitrationCost;
354
- transaction.senderFee = _arbitrationCost;
355
- transaction.sender .send (extraFeeSender ); // It is the user responsibility to accept ETH.
351
+ // Refund buyer if he overpaid.
352
+ if (transaction.buyerFee > _arbitrationCost) {
353
+ uint256 extraFeeBuyer = transaction.buyerFee - _arbitrationCost;
354
+ transaction.buyerFee = _arbitrationCost;
355
+ transaction.buyer .send (extraFeeBuyer ); // It is the user responsibility to accept ETH.
356
356
}
357
357
358
- // Refund receiver if he overpaid.
359
- if (transaction.receiverFee > _arbitrationCost) {
360
- uint256 extraFeeReceiver = transaction.receiverFee - _arbitrationCost;
361
- transaction.receiverFee = _arbitrationCost;
362
- transaction.receiver .send (extraFeeReceiver ); // It is the user responsibility to accept ETH.
358
+ // Refund seller if he overpaid.
359
+ if (transaction.sellerFee > _arbitrationCost) {
360
+ uint256 extraFeeSeller = transaction.sellerFee - _arbitrationCost;
361
+ transaction.sellerFee = _arbitrationCost;
362
+ transaction.seller .send (extraFeeSeller ); // It is the user responsibility to accept ETH.
363
363
}
364
364
}
365
365
366
366
/// @dev Execute a ruling of a dispute. It reimburses the fee to the winning party.
367
367
/// @param _transactionID The index of the transaction.
368
- /// @param _ruling Ruling given by the arbitrator. 1 : Reimburse the receiver . 2 : Pay the sender .
368
+ /// @param _ruling Ruling given by the arbitrator. 1 : Reimburse the seller . 2 : Pay the buyer .
369
369
function executeRuling (uint256 _transactionID , uint256 _ruling ) internal {
370
370
Transaction storage transaction = transactions[_transactionID];
371
371
// Give the arbitration fee back.
372
372
// Note that we use send to prevent a party from blocking the execution.
373
- if (_ruling == uint256 (Party.Sender )) {
374
- transaction.sender .send (transaction.senderFee + transaction.amount);
375
- } else if (_ruling == uint256 (Party.Receiver )) {
376
- transaction.receiver .send (transaction.receiverFee + transaction.amount);
373
+ if (_ruling == uint256 (Party.Buyer )) {
374
+ transaction.buyer .send (transaction.buyerFee + transaction.amount);
375
+ } else if (_ruling == uint256 (Party.Seller )) {
376
+ transaction.seller .send (transaction.sellerFee + transaction.amount);
377
377
} else {
378
- uint256 splitAmount = (transaction.senderFee + transaction.amount) / 2 ;
379
- transaction.sender .send (splitAmount);
380
- transaction.receiver .send (splitAmount);
378
+ uint256 splitAmount = (transaction.buyerFee + transaction.amount) / 2 ;
379
+ transaction.buyer .send (splitAmount);
380
+ transaction.seller .send (splitAmount);
381
381
}
382
382
383
383
transaction.amount = 0 ;
384
- transaction.senderFee = 0 ;
385
- transaction.receiverFee = 0 ;
384
+ transaction.buyerFee = 0 ;
385
+ transaction.sellerFee = 0 ;
386
386
transaction.status = Status.TransactionResolved;
387
387
388
388
emit TransactionResolved (_transactionID, Resolution.RulingEnforced);
@@ -403,17 +403,17 @@ contract Escrow is IArbitrableV2 {
403
403
// ************************************* //
404
404
405
405
error GovernorOnly ();
406
- error SenderOnly ();
407
- error ReceiverOnly ();
406
+ error BuyerOnly ();
407
+ error SellerOnly ();
408
408
error ArbitratorOnly ();
409
409
error TransactionDisputed ();
410
410
error MaximumPaymentAmountExceeded ();
411
411
error DisputeAlreadyCreatedOrTransactionAlreadyExecuted ();
412
412
error DeadlineNotPassed ();
413
- error SenderFeeNotCoverArbitrationCosts ();
414
- error ReceiverFeeNotCoverArbitrationCosts ();
415
- error NotWaitingForReceiverFees ();
416
- error NotWaitingForSenderFees ();
413
+ error BuyerFeeNotCoverArbitrationCosts ();
414
+ error SellerFeeNotCoverArbitrationCosts ();
415
+ error NotWaitingForSellerFees ();
416
+ error NotWaitingForBuyerFees ();
417
417
error TimeoutNotPassed ();
418
418
error InvalidRuling ();
419
419
error DisputeAlreadyResolved ();
0 commit comments