forked from Synthetixio/synthetix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCollateralUtil.sol
96 lines (76 loc) · 3.69 KB
/
CollateralUtil.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
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
// Inheritance
import "./interfaces/IAddressResolver.sol";
import "./interfaces/ICollateralUtil.sol";
import "./interfaces/ICollateralLoan.sol";
import "./interfaces/IExchangeRates.sol";
import "./MixinSystemSettings.sol";
import "./SafeDecimalMath.sol";
contract CollateralUtil is ICollateralUtil, ICollateralLoan, MixinSystemSettings {
/* ========== LIBRARIES ========== */
using SafeMath for uint;
using SafeDecimalMath for uint;
/* ========== CONSTANTS ========== */
bytes32 private constant sUSD = "sUSD";
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory newAddresses = new bytes32[](1);
newAddresses[0] = CONTRACT_EXRATES;
addresses = combineArrays(existingAddresses, newAddresses);
}
/* ---------- Related Contracts ---------- */
function _exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(resolver.requireAndGetAddress(CONTRACT_EXRATES, "Missing ExchangeRates contract"));
}
constructor(address _resolver) public MixinSystemSettings(_resolver) {}
/* ========== UTILITY VIEW FUNCS ========== */
function getCollateralRatio(Loan calldata loan, bytes32 collateralKey) external view returns (uint cratio) {
uint cvalue = _exchangeRates().effectiveValue(collateralKey, loan.collateral, sUSD);
uint dvalue = _exchangeRates().effectiveValue(loan.currency, loan.amount.add(loan.accruedInterest), sUSD);
return cvalue.divideDecimal(dvalue);
}
function maxLoan(
uint amount,
bytes32 currency,
uint minCratio,
bytes32 collateralKey
) external view returns (uint max) {
uint ratio = SafeDecimalMath.unit().divideDecimalRound(minCratio);
return ratio.multiplyDecimal(_exchangeRates().effectiveValue(collateralKey, amount, currency));
}
/**
* r = target issuance ratio
* D = debt value in sUSD
* V = collateral value in sUSD
* P = liquidation penalty
* Calculates amount of synths = (D - V * r) / (1 - (1 + P) * r)
* Note: if you pass a loan in here that is not eligible for liquidation it will revert.
* We check the ratio first in liquidateInternal and only pass eligible loans in.
*/
function liquidationAmount(
Loan calldata loan,
uint minCratio,
bytes32 collateralKey
) external view returns (uint amount) {
uint liquidationPenalty = getLiquidationPenalty();
uint debtValue = _exchangeRates().effectiveValue(loan.currency, loan.amount.add(loan.accruedInterest), sUSD);
uint collateralValue = _exchangeRates().effectiveValue(collateralKey, loan.collateral, sUSD);
uint unit = SafeDecimalMath.unit();
uint dividend = debtValue.sub(collateralValue.divideDecimal(minCratio));
uint divisor = unit.sub(unit.add(liquidationPenalty).divideDecimal(minCratio));
uint sUSDamount = dividend.divideDecimal(divisor);
return _exchangeRates().effectiveValue(sUSD, sUSDamount, loan.currency);
}
function collateralRedeemed(
bytes32 currency,
uint amount,
bytes32 collateralKey
) external view returns (uint collateral) {
uint liquidationPenalty = getLiquidationPenalty();
collateral = _exchangeRates().effectiveValue(currency, amount, collateralKey);
return collateral.multiplyDecimal(SafeDecimalMath.unit().add(liquidationPenalty));
}
}