-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathTrader.sol
More file actions
99 lines (81 loc) · 4.94 KB
/
Trader.sol
File metadata and controls
99 lines (81 loc) · 4.94 KB
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
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.0;
pragma abicoder v2;
import 'uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
import 'uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
contract SwapExamples {
// For the scope of these swap examples,
// we will detail the design considerations when using
// `exactInput`, `exactInputSingle`, `exactOutput`, and `exactOutputSingle`.
// It should be noted that for the sake of these examples, we purposefully pass in the swap router instead of inherit the swap router for simplicity.
// More advanced example contracts will detail how to inherit the swap router safely.
ISwapRouter public immutable swapRouter;
address public immutable token0;
address public immutable token1;
address public immutable fee;
constructor(ISwapRouter _swapRouter, _token0, _token1, _fee) {
swapRouter = _swapRouter;
token0 = _token0;
token1 = _token1;
fee = _fee;
}
/// @notice swapExactInputSingle swaps a fixed amount of DAI for a maximum possible amount of WETH9
/// using the DAI/WETH9 0.3% pool by calling `exactInputSingle` in the swap router.
/// @dev The calling address must approve this contract to spend at least `amountIn` worth of its DAI for this function to succeed.
/// @param amountIn The exact amount of DAI that will be swapped for WETH9.
/// @return amountOut The amount of WETH9 received.
function swapExactInputSingle(uint256 _amountIn, uint256 _amountOutMinimum, uint256 _sqrtPriceLimitX96) external returns (uint256 amountOut) {
// msg.sender must approve this contract
// Transfer the specified amount of DAI to this contract.
TransferHelper.safeTransferFrom(token0, msg.sender, address(this), amountIn);
// Approve the router to spend DAI.
TransferHelper.safeApprove(token0, address(swapRouter), amountIn);
// Naively set amountOutMinimum to 0. In production, use an oracle or other data source to choose a safer value for amountOutMinimum.
// We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.
ISwapRouter.ExactInputSingleParams memory params =
ISwapRouter.ExactInputSingleParams({
tokenIn: token0,
tokenOut: token1,
fee: fee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: _amountOutMinimum,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
// The call to `exactInputSingle` executes the swap.
amountOut = swapRouter.exactInputSingle(params);
}
/// @notice swapExactOutputSingle swaps a minimum possible amount of DAI for a fixed amount of WETH.
/// @dev The calling address must approve this contract to spend its DAI for this function to succeed. As the amount of input DAI is variable,
/// the calling address will need to approve for a slightly higher amount, anticipating some variance.
/// @param amountOut The exact amount of WETH9 to receive from the swap.
/// @param amountInMaximum The amount of DAI we are willing to spend to receive the specified amount of WETH9.
/// @return amountIn The amount of DAI actually spent in the swap.
function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum, uint256 _sqrtPriceLimitX96) external returns (uint256 amountIn) {
// Transfer the specified amount of DAI to this contract.
TransferHelper.safeTransferFrom(token0, msg.sender, address(this), amountInMaximum);
// Approve the router to spend the specifed `amountInMaximum` of DAI.
// In production, you should choose the maximum amount to spend based on oracles or other data sources to acheive a better swap.
TransferHelper.safeApprove(token0, address(swapRouter), amountInMaximum);
ISwapRouter.ExactOutputSingleParams memory params =
ISwapRouter.ExactOutputSingleParams({
tokenIn: token0,
tokenOut: token1,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountOut: amountOut,
amountInMaximum: amountInMaximum,
sqrtPriceLimitX96: _sqrtPriceLimitX96
});
// Executes the swap returning the amountIn needed to spend to receive the desired amountOut.
amountIn = swapRouter.exactOutputSingle(params);
// For exact output swaps, the amountInMaximum may not have all been spent.
// If the actual amount spent (amountIn) is less than the specified maximum amount, we must refund the msg.sender and approve the swapRouter to spend 0.
if (amountIn < amountInMaximum) {
TransferHelper.safeApprove(token0, address(swapRouter), 0);
TransferHelper.safeTransfer(token0, msg.sender, amountInMaximum - amountIn);
}
}
}