@@ -3,141 +3,104 @@ pragma solidity ^0.5.16;
3
3
import "./CErc20.sol " ;
4
4
import "./CToken.sol " ;
5
5
import "./PriceOracle.sol " ;
6
- import "./Comptroller.sol " ;
7
- import "./SafeMath.sol " ;
8
6
9
7
interface V1PriceOracleInterface {
10
8
function assetPrices (address asset ) external view returns (uint );
11
9
}
12
10
13
11
contract PriceOracleProxy is PriceOracle {
14
- using SafeMath for uint256 ;
12
+ /// @notice Indicator that this is a PriceOracle contract (for inspection)
13
+ bool public constant isPriceOracle = true ;
15
14
16
- /**
17
- * @notice The v1 price oracle, which will continue to serve prices for v1 assets
18
- */
15
+ /// @notice The v1 price oracle, which will continue to serve prices for v1 assets
19
16
V1PriceOracleInterface public v1PriceOracle;
20
17
21
- /**
22
- * @notice The comptroller which is used to white-list assets the proxy will price
23
- * @dev Assets which are not white-listed will not be priced, to defend against abuse
24
- */
25
- Comptroller public comptroller;
18
+ /// @notice Address of the guardian, which may set the SAI price once
19
+ address public guardian;
26
20
27
- /**
28
- * @notice address of the cEther contract, which has a constant price
29
- */
21
+ /// @notice Address of the cEther contract, which has a constant price
30
22
address public cEthAddress;
31
23
32
- /**
33
- * @notice address of the cUSDC contract, which we hand pick a key for
34
- */
24
+ /// @notice Address of the cUSDC contract, which we hand pick a key for
35
25
address public cUsdcAddress;
36
26
37
- /**
38
- * @notice address of the cSAI contract, which we hand pick a key for
39
- */
27
+ /// @notice Address of the cSAI contract, which we hand pick a key for
40
28
address public cSaiAddress;
41
29
42
- /**
43
- * @notice address of the cDAI contract, which we peg to the SAI price
44
- */
30
+ /// @notice Address of the cDAI contract, which we hand pick a key for
45
31
address public cDaiAddress;
46
32
47
- /**
48
- * @notice address of the USDC contract, which we hand pick a key for
49
- */
50
- address constant usdcOracleKey = address (1 );
51
-
52
- /**
53
- * @notice address of the SAI contract, which we hand pick a key for
54
- */
55
- address constant saiOracleKey = address (2 );
33
+ /// @notice Handpicked key for USDC
34
+ address public constant usdcOracleKey = address (1 );
56
35
57
- /**
58
- * @notice address of the asset which contains the USD/ETH price from Maker
59
- */
60
- address public makerUsdOracleKey;
36
+ /// @notice Handpicked key for DAI
37
+ address public constant daiOracleKey = address (2 );
61
38
62
- /**
63
- * @notice Indicator that this is a PriceOracle contract (for inspection)
64
- */
65
- bool public constant isPriceOracle = true ;
39
+ /// @notice Frozen SAI price (or 0 if not set yet)
40
+ uint public saiPrice;
66
41
67
42
/**
68
- * @param comptroller_ The address of the comptroller , which will be consulted for market listing status
43
+ * @param guardian_ The address of the guardian , which may set the SAI price once
69
44
* @param v1PriceOracle_ The address of the v1 price oracle, which will continue to operate and hold prices for collateral assets
70
45
* @param cEthAddress_ The address of cETH, which will return a constant 1e18, since all prices relative to ether
71
46
* @param cUsdcAddress_ The address of cUSDC, which will be read from a special oracle key
72
- * @param cSaiAddress_ The address of cSAI, which will be read from a special oracle key
73
- * @param cDaiAddress_ The address of cDAI, which will be pegged to the SAI price
47
+ * @param cSaiAddress_ The address of cSAI, which will be read directly from storage
48
+ * @param cDaiAddress_ The address of cDAI, which will be read from a special oracle key
74
49
*/
75
- constructor (address comptroller_ ,
50
+ constructor (address guardian_ ,
76
51
address v1PriceOracle_ ,
77
52
address cEthAddress_ ,
78
53
address cUsdcAddress_ ,
79
54
address cSaiAddress_ ,
80
55
address cDaiAddress_ ) public {
81
- comptroller = Comptroller (comptroller_) ;
56
+ guardian = guardian_ ;
82
57
v1PriceOracle = V1PriceOracleInterface (v1PriceOracle_);
83
58
84
59
cEthAddress = cEthAddress_;
85
60
cUsdcAddress = cUsdcAddress_;
86
61
cSaiAddress = cSaiAddress_;
87
62
cDaiAddress = cDaiAddress_;
88
-
89
- if (cSaiAddress_ != address (0 )) {
90
- makerUsdOracleKey = CErc20 (cSaiAddress_).underlying ();
91
- }
92
63
}
93
64
94
65
/**
95
66
* @notice Get the underlying price of a listed cToken asset
96
67
* @param cToken The cToken to get the underlying price of
97
- * @return The underlying asset price mantissa (scaled by 1e18).
98
- * Zero means the price is unavailable.
68
+ * @return The underlying asset price mantissa (scaled by 1e18)
99
69
*/
100
70
function getUnderlyingPrice (CToken cToken ) public view returns (uint ) {
101
71
address cTokenAddress = address (cToken);
102
- (bool isListed , ) = comptroller.markets (cTokenAddress);
103
-
104
- if (! isListed) {
105
- // not white-listed, worthless
106
- return 0 ;
107
- }
108
72
109
73
if (cTokenAddress == cEthAddress) {
110
74
// ether always worth 1
111
75
return 1e18 ;
112
76
}
113
77
114
78
if (cTokenAddress == cUsdcAddress) {
115
- // we assume USDC/USD = 1, and let DAI/ETH float based on the DAI/USDC ratio
116
- // use the maker usd price (for a token w/ 6 decimals)
117
- return v1PriceOracle.assetPrices (makerUsdOracleKey).mul (1e12 ); // 1e(18 - 6)
79
+ return v1PriceOracle.assetPrices (usdcOracleKey);
118
80
}
119
81
120
- if (cTokenAddress == cSaiAddress || cTokenAddress == cDaiAddress) {
121
- // check and bound the DAI/USDC posted price ratio
122
- // and use that to scale the maker price (for a token w/ 18 decimals)
123
- uint makerUsdPrice = v1PriceOracle.assetPrices (makerUsdOracleKey);
124
- uint postedUsdcPrice = v1PriceOracle.assetPrices (usdcOracleKey);
125
- uint postedScaledDaiPrice = v1PriceOracle.assetPrices (saiOracleKey).mul (1e12 );
126
- uint daiUsdcRatio = postedScaledDaiPrice.mul (1e18 ).div (postedUsdcPrice);
127
-
128
- if (daiUsdcRatio < 0.95e18 ) {
129
- return makerUsdPrice.mul (0.95e18 ).div (1e18 );
130
- }
131
-
132
- if (daiUsdcRatio > 1.05e18 ) {
133
- return makerUsdPrice.mul (1.05e18 ).div (1e18 );
134
- }
82
+ if (cTokenAddress == cDaiAddress) {
83
+ return v1PriceOracle.assetPrices (daiOracleKey);
84
+ }
135
85
136
- return makerUsdPrice.mul (daiUsdcRatio).div (1e18 );
86
+ if (cTokenAddress == cSaiAddress) {
87
+ // use the frozen SAI price if set, otherwise use the DAI price
88
+ return saiPrice > 0 ? saiPrice : v1PriceOracle.assetPrices (daiOracleKey);
137
89
}
138
90
139
91
// otherwise just read from v1 oracle
140
92
address underlying = CErc20 (cTokenAddress).underlying ();
141
93
return v1PriceOracle.assetPrices (underlying);
142
94
}
95
+
96
+ /**
97
+ * @notice Set the price of SAI, permanently
98
+ * @param price The price for SAI
99
+ */
100
+ function setSaiPrice (uint price ) public {
101
+ require (msg .sender == guardian, "only guardian may set the SAI price " );
102
+ require (saiPrice == 0 , "SAI price may only be set once " );
103
+ require (price < 0.1e18 , "SAI price must be < 0.1 ETH " );
104
+ saiPrice = price;
105
+ }
143
106
}
0 commit comments