-
Notifications
You must be signed in to change notification settings - Fork 31
/
Swaplace.sol
129 lines (100 loc) · 3.2 KB
/
Swaplace.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import {IERC165} from "./interfaces/IERC165.sol";
import {ISwaplace} from "./interfaces/ISwaplace.sol";
import {ITransfer} from "./interfaces/ITransfer.sol";
import {SwapFactory} from "./SwapFactory.sol";
/**
* @author @0xneves | @blockful_io
* @dev Swaplace is a Decentralized Feeless DEX. It has no owners, it cannot be stopped.
* Its cern is to facilitate swaps between virtual assets following the ERC standard.
* Users can propose or accept swaps by allowing Swaplace to move their assets using the
* `approve` or `permit` function.
*/
contract Swaplace is SwapFactory, ISwaplace, IERC165 {
/// @dev Swap Identifier counter.
uint256 private _totalSwaps;
/// @dev Mapping of Swap ID to Swap struct. See {ISwap-Swap}.
mapping(uint256 => Swap) private _swaps;
/**
* @dev See {ISwaplace-createSwap}.
*/
function createSwap(Swap calldata swap) public returns (uint256) {
if (swap.owner != msg.sender) revert InvalidAddress(msg.sender);
assembly {
sstore(_totalSwaps.slot, add(sload(_totalSwaps.slot), 1))
}
uint256 swapId = _totalSwaps;
_swaps[swapId] = swap;
(address allowed, ) = parseData(swap.config);
emit SwapCreated(swapId, msg.sender, allowed);
return swapId;
}
/**
* @dev See {ISwaplace-acceptSwap}.
*/
function acceptSwap(uint256 swapId, address receiver) public returns (bool) {
Swap memory swap = _swaps[swapId];
(address allowed, uint256 expiry) = parseData(swap.config);
if (allowed != address(0) && allowed != msg.sender)
revert InvalidAddress(msg.sender);
if (expiry < block.timestamp) revert InvalidExpiry(expiry);
_swaps[swapId].config = 0;
Asset[] memory assets = swap.asking;
for (uint256 i = 0; i < assets.length; ) {
ITransfer(assets[i].addr).transferFrom(
msg.sender,
swap.owner,
assets[i].amountOrId
);
assembly {
i := add(i, 1)
}
}
assets = swap.biding;
for (uint256 i = 0; i < assets.length; ) {
ITransfer(assets[i].addr).transferFrom(
swap.owner,
receiver,
assets[i].amountOrId
);
assembly {
i := add(i, 1)
}
}
emit SwapAccepted(swapId, swap.owner, msg.sender);
return true;
}
/**
* @dev See {ISwaplace-cancelSwap}.
*/
function cancelSwap(uint256 swapId) public {
if (_swaps[swapId].owner != msg.sender) revert InvalidAddress(msg.sender);
(, uint256 expiry) = parseData(_swaps[swapId].config);
if (expiry < block.timestamp) revert InvalidExpiry(expiry);
_swaps[swapId].config = 0;
emit SwapCanceled(swapId, msg.sender);
}
/**
* @dev See {ISwaplace-getSwap}.
*/
function getSwap(uint256 swapId) public view returns (Swap memory) {
return _swaps[swapId];
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceID
) external pure override(IERC165) returns (bool) {
return
interfaceID == type(IERC165).interfaceId ||
interfaceID == type(ISwaplace).interfaceId;
}
/**
* @dev Getter function for _totalSwaps.
*/
function totalSwaps() public view returns (uint256) {
return _totalSwaps;
}
}