-
Notifications
You must be signed in to change notification settings - Fork 18
/
SushiXSwapV2.sol
201 lines (170 loc) · 5.44 KB
/
SushiXSwapV2.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.10;
import "./interfaces/ISushiXSwapV2.sol";
/// @title SushiXSwapV2
/// @notice Cross-chain swaps & general message passing through adapters
contract SushiXSwapV2 is ISushiXSwapV2, Ownable {
using SafeERC20 for IERC20;
IRouteProcessor public rp;
mapping(address => bool) public approvedAdapters;
mapping(address => bool) privilegedUsers;
address constant NATIVE_ADDRESS =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
IWETH public immutable weth;
uint8 private unlocked = 1;
uint8 private paused = 1;
constructor(IRouteProcessor _rp, address _weth) {
rp = _rp;
weth = IWETH(_weth);
}
modifier onlyApprovedAdapters(address _adapter) {
require(approvedAdapters[_adapter], "Not Approved Adatper");
_;
}
modifier onlyOwnerOrPrivilegedUser() {
require(
msg.sender == owner() || privilegedUsers[msg.sender] == true,
"SushiXSwapV2 not owner or privy user"
);
_;
}
modifier lock() {
require(unlocked == 1, "SushiXSwapV2 is locked");
require(paused == 1, "SushiXSwapV2 is paused");
unlocked = 2;
_;
unlocked = 1;
}
/// @notice Set an adddress as privileged user
/// @param user The address to set
/// @param privileged The status of users's privileged status
function setPrivileged(address user, bool privileged) external onlyOwner {
privilegedUsers[user] = privileged;
}
/// @notice pause the contract
function pause() external onlyOwnerOrPrivilegedUser {
paused = 2;
}
/// @notice resume the contract from paused state
function resume() external onlyOwnerOrPrivilegedUser {
paused = 1;
}
/// @inheritdoc ISushiXSwapV2
function updateAdapterStatus(
address _adapter,
bool _status
) external onlyOwner {
approvedAdapters[_adapter] = _status;
}
/// @inheritdoc ISushiXSwapV2
function updateRouteProcessor(
address newRouteProcessor
) external onlyOwner {
rp = IRouteProcessor(newRouteProcessor);
}
/// @inheritdoc ISushiXSwapV2
function swap(bytes memory _swapData) external payable override lock {
// just swap
_swap(_swapData);
}
function _swap(bytes memory _swapData) internal {
// internal just swap
IRouteProcessor.RouteProcessorData memory rpd = abi.decode(
_swapData,
(IRouteProcessor.RouteProcessorData)
);
if (rpd.tokenIn != NATIVE_ADDRESS) {
IERC20(rpd.tokenIn).safeTransferFrom(
msg.sender,
address(rp),
rpd.amountIn
);
}
rp.processRoute{
value: rpd.tokenIn == NATIVE_ADDRESS ? rpd.amountIn : 0
}(
rpd.tokenIn,
rpd.amountIn,
rpd.tokenOut,
rpd.amountOutMin,
rpd.to,
rpd.route
);
}
/// @inheritdoc ISushiXSwapV2
function sendMessage(
address _adapter,
bytes calldata _adapterData
) external payable override lock onlyApprovedAdapters(_adapter) {
// send cross chain message
ISushiXSwapV2Adapter(_adapter).sendMessage(_adapterData);
}
/// @inheritdoc ISushiXSwapV2
function bridge(
BridgeParams calldata _bridgeParams,
address _refundAddress,
bytes calldata _swapPayload,
bytes calldata _payloadData
)
external
payable
override
lock
onlyApprovedAdapters(_bridgeParams.adapter)
{
// bridge
if (_bridgeParams.tokenIn != NATIVE_ADDRESS) {
IERC20(_bridgeParams.tokenIn).safeTransferFrom(
msg.sender,
_bridgeParams.adapter,
_bridgeParams.amountIn
);
}
ISushiXSwapV2Adapter(_bridgeParams.adapter).adapterBridge{
value: address(this).balance
}(_bridgeParams.adapterData, _refundAddress, _swapPayload, _payloadData);
emit BridgeOnSource(
_bridgeParams.refId,
msg.sender,
_bridgeParams.adapter
);
}
/// @inheritdoc ISushiXSwapV2
function swapAndBridge(
BridgeParams calldata _bridgeParams,
address _refundAddress,
bytes calldata _swapData,
bytes calldata _swapPayload,
bytes calldata _payloadData
)
external
payable
override
lock
onlyApprovedAdapters(_bridgeParams.adapter)
{
// swap and bridge
_swap(_swapData);
ISushiXSwapV2Adapter(_bridgeParams.adapter).adapterBridge{
value: address(this).balance
}(_bridgeParams.adapterData, _refundAddress, _swapPayload, _payloadData);
emit SwapAndBridgeOnSource(
_bridgeParams.refId,
msg.sender,
_bridgeParams.adapter
);
}
/// @notice Rescue tokens from the contract
/// @param _token The address of the token to rescue
/// @param _to The address to send the tokens to
function rescueTokens(address _token, address _to) external onlyOwner {
if (_token != NATIVE_ADDRESS) {
IERC20(_token).safeTransfer(
_to,
IERC20(_token).balanceOf(address(this))
);
} else {
_to.call{value: (address(this).balance)}("");
}
}
}