This repository has been archived by the owner on Nov 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ExchangeRate.sol
108 lines (94 loc) · 4.6 KB
/
ExchangeRate.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
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity =0.7.6;
pragma abicoder v2;
import {LibStorage} from "../../global/LibStorage.sol";
import {Constants} from "../../global/Constants.sol";
import {ETHRate, ETHRateStorage} from "../../global/Types.sol";
import {SafeInt256} from "../../math/SafeInt256.sol";
import {AggregatorV2V3Interface} from "../../../interfaces/chainlink/AggregatorV2V3Interface.sol";
library ExchangeRate {
using SafeInt256 for int256;
/// @notice Converts a balance to ETH from a base currency. Buffers or haircuts are
/// always applied in this method.
/// @param er exchange rate object from base to ETH
/// @return the converted balance denominated in ETH with Constants.INTERNAL_TOKEN_PRECISION
function convertToETH(ETHRate memory er, int256 balance) internal pure returns (int256) {
int256 multiplier = balance > 0 ? er.haircut : er.buffer;
// We are converting internal balances here so we know they have INTERNAL_TOKEN_PRECISION decimals
// internalDecimals * rateDecimals * multiplier / (rateDecimals * multiplierDecimals)
// Therefore the result is in ethDecimals
int256 result =
balance.mul(er.rate).mul(multiplier).div(Constants.PERCENTAGE_DECIMALS).div(
er.rateDecimals
);
return result;
}
/// @notice Converts the balance denominated in ETH to the equivalent value in a base currency.
/// Buffers and haircuts ARE NOT applied in this method.
/// @param er exchange rate object from base to ETH
/// @param balance amount (denominated in ETH) to convert
function convertETHTo(ETHRate memory er, int256 balance) internal pure returns (int256) {
// We are converting internal balances here so we know they have INTERNAL_TOKEN_PRECISION decimals
// internalDecimals * rateDecimals / rateDecimals
int256 result = balance.mul(er.rateDecimals).div(er.rate);
return result;
}
/// @notice Calculates the exchange rate between two currencies via ETH. Returns the rate denominated in
/// base exchange rate decimals: (baseRateDecimals * quoteRateDecimals) / quoteRateDecimals
/// @param baseER base exchange rate struct
/// @param quoteER quote exchange rate struct
function exchangeRate(ETHRate memory baseER, ETHRate memory quoteER)
internal
pure
returns (int256)
{
return baseER.rate.mul(quoteER.rateDecimals).div(quoteER.rate);
}
/// @notice Returns an ETHRate object used to calculate free collateral
function buildExchangeRate(uint256 currencyId) internal view returns (ETHRate memory) {
mapping(uint256 => ETHRateStorage) storage store = LibStorage.getExchangeRateStorage();
ETHRateStorage storage ethStorage = store[currencyId];
int256 rateDecimals;
int256 rate;
if (currencyId == Constants.ETH_CURRENCY_ID) {
// ETH rates will just be 1e18, but will still have buffers, haircuts,
// and liquidation discounts
rateDecimals = Constants.ETH_DECIMALS;
rate = Constants.ETH_DECIMALS;
} else {
// prettier-ignore
(
/* roundId */,
rate,
/* uint256 startedAt */,
/* updatedAt */,
/* answeredInRound */
) = ethStorage.rateOracle.latestRoundData();
require(rate > 0);
// No overflow, restricted on storage
rateDecimals = int256(10**ethStorage.rateDecimalPlaces);
if (ethStorage.mustInvert) {
rate = rateDecimals.mul(rateDecimals).div(rate);
}
}
int256 buffer = ethStorage.buffer;
if (buffer > Constants.MIN_BUFFER_SCALE) {
// Buffers from 100 to 150 are 1-1 (i.e. a buffer of 150 is a 150% increase)
// in the debt amount. Buffers from 151 to 255 are scaled by a multiple of 10
// units to allow for much higher buffers at the outer limits. A stored
// buffer value of 151 = 150 + 10 = 160.
// The max buffer value of of 255 = 150 + 105 * 10 = 1200.
// No possibility of overflows due to storage size and constant definition
buffer = (buffer - Constants.MIN_BUFFER_SCALE) * Constants.BUFFER_SCALE
+ Constants.MIN_BUFFER_SCALE;
}
return
ETHRate({
rateDecimals: rateDecimals,
rate: rate,
buffer: buffer,
haircut: ethStorage.haircut,
liquidationDiscount: ethStorage.liquidationDiscount
});
}
}