This repository has been archived by the owner on Sep 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 29
/
ConditionUniswapV2Rate.sol
142 lines (124 loc) · 4.19 KB
/
ConditionUniswapV2Rate.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.10;
pragma experimental ABIEncoderV2;
import {GelatoConditionsStandard} from "../../GelatoConditionsStandard.sol";
import {IUniswapV2Router02, IUniswapV2Factory, IWETH} from "../../../dapp_interfaces/uniswap_v2/IUniswapV2.sol";
import {SafeMath} from "../../../external/SafeMath.sol";
import {IGelatoCore} from "../../../gelato_core/interfaces/IGelatoCore.sol";
import {IERC20} from "../../../external/IERC20.sol";
contract ConditionUniswapV2Rate is GelatoConditionsStandard {
using SafeMath for uint256;
IUniswapV2Router02 public immutable uniRouter;
IUniswapV2Factory public immutable uniFactory;
IWETH public immutable WETH;
address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// userProxy => taskReceipt.id => refPrice
mapping(address => mapping(uint256 => uint256)) public refRate;
constructor(
IUniswapV2Router02 _uniswapV2Router,
IUniswapV2Factory _uniswapV2Factory,
IWETH _weth
)
public
{
uniRouter = _uniswapV2Router;
uniFactory = _uniswapV2Factory;
WETH = _weth;
}
/// @dev use this function to encode the data off-chain for the condition data field
function getConditionData(
address _sellToken,
uint256 _sellAmount,
address _buyToken,
uint256 _currentRefRate,
bool _greaterElseSmaller
)
public
pure
virtual
returns(bytes memory)
{
return abi.encodeWithSelector(
this.checkRefRateUniswap.selector,
_sellToken,
_sellAmount,
_buyToken,
_currentRefRate,
_greaterElseSmaller
);
}
// STANDARD Interface
/// @param _conditionData The encoded data from getConditionData()
function ok(uint256, bytes calldata _conditionData, uint256)
public
view
virtual
override
returns(string memory)
{
(address sendToken,
uint256 sendAmount,
address buyToken,
uint256 currentRefRate,
bool greaterElseSmaller
) = abi.decode(
_conditionData[4:], // slice out selector & taskReceiptId
(address,uint256,address,uint256,bool)
);
return checkRefRateUniswap(
sendToken, sendAmount, buyToken, currentRefRate, greaterElseSmaller
);
}
// Specific Implementation
function checkRefRateUniswap(
address _sellToken,
uint256 _sellAmount,
address _buyToken,
uint256 _currentRefRate,
bool _greaterElseSmaller
)
public
view
virtual
returns(string memory)
{
(_sellToken, _buyToken) = convertEthToWeth(_sellToken, _buyToken);
uint256 expectedRate = getUniswapRate(_sellToken, _sellAmount, _buyToken);
if (_greaterElseSmaller) { // greaterThan
if (expectedRate >= _currentRefRate) return OK;
else return "ExpectedRateIsNotGreaterThanRefRate";
} else { // smallerThan
if (expectedRate <= _currentRefRate) return OK;
else return "ExpectedRateIsNotSmallerThanRefRate";
}
}
function getPaths(address _sellToken, address _buyToken)
internal pure returns(address[] memory paths)
{
paths = new address[](2);
paths[0] = _sellToken;
paths[1] = _buyToken;
}
function getUniswapRate(address _sellToken, uint256 _sellAmount, address _buyToken)
public
view
returns(uint256 expectedRate)
{
address[] memory tokenPath = getPaths(_sellToken, _buyToken);
try uniRouter.getAmountsOut(_sellAmount, tokenPath)
returns (uint[] memory expectedRates) {
expectedRate = expectedRates[1];
} catch {
revert("UniswapV2GetExpectedRateError");
}
}
function convertEthToWeth(address _sellToken, address _buyToken)
private
view
returns(address, address)
{
if (_sellToken == ETH_ADDRESS) _sellToken = address(WETH);
if (_buyToken == ETH_ADDRESS) _buyToken = address(WETH);
return (_sellToken, _buyToken);
}
}