forked from Synthetixio/synthetix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCollateralShort.sol
155 lines (120 loc) · 5.49 KB
/
CollateralShort.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
143
144
145
146
147
148
149
150
151
152
153
154
155
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
// Inheritance
import "./Collateral.sol";
contract CollateralShort is Collateral {
constructor(
address _owner,
ICollateralManager _manager,
address _resolver,
bytes32 _collateralKey,
uint _minCratio,
uint _minCollateral
) public Collateral(_owner, _manager, _resolver, _collateralKey, _minCratio, _minCollateral) {}
function open(
uint collateral,
uint amount,
bytes32 currency
) external returns (uint id) {
// Transfer from will throw if they didn't set the allowance
IERC20(address(_synthsUSD())).transferFrom(msg.sender, address(this), collateral);
id = _open(collateral, amount, currency, true);
}
function close(uint id) external returns (uint amount, uint collateral) {
(amount, collateral) = _close(msg.sender, id);
IERC20(address(_synthsUSD())).transfer(msg.sender, collateral);
}
function deposit(
address borrower,
uint id,
uint amount
) external returns (uint principal, uint collateral) {
require(amount <= IERC20(address(_synthsUSD())).allowance(msg.sender, address(this)), "Allowance too low");
IERC20(address(_synthsUSD())).transferFrom(msg.sender, address(this), amount);
(principal, collateral) = _deposit(borrower, id, amount);
}
function withdraw(uint id, uint amount) external returns (uint principal, uint collateral) {
(principal, collateral) = _withdraw(id, amount);
IERC20(address(_synthsUSD())).transfer(msg.sender, amount);
}
function repay(
address borrower,
uint id,
uint amount
) external returns (uint principal, uint collateral) {
(principal, collateral) = _repay(borrower, msg.sender, id, amount);
}
function closeWithCollateral(uint id) external returns (uint amount, uint collateral) {
(amount, collateral) = _closeWithCollateral(msg.sender, id);
if (collateral > 0) {
IERC20(address(_synthsUSD())).transfer(msg.sender, collateral);
}
}
function repayWithCollateral(uint id, uint amount) external returns (uint principal, uint collateral) {
(principal, collateral) = _repayWithCollateral(msg.sender, id, amount);
}
// Needed for Lyra.
function getShortAndCollateral(
address, /* borrower */
uint id
) external view returns (uint principal, uint collateral) {
Loan memory loan = loans[id];
return (loan.amount, loan.collateral);
}
function draw(uint id, uint amount) external returns (uint principal, uint collateral) {
(principal, collateral) = _draw(id, amount);
}
function liquidate(
address borrower,
uint id,
uint amount
) external {
uint collateralLiquidated = _liquidate(borrower, id, amount);
IERC20(address(_synthsUSD())).transfer(msg.sender, collateralLiquidated);
}
function _repayWithCollateral(
address borrower,
uint id,
uint payment
) internal rateIsValid issuanceIsActive returns (uint amount, uint collateral) {
// 0. Get the loan to repay and accrue interest.
Loan storage loan = _getLoanAndAccrueInterest(id, borrower);
// 1. Check loan is open and last interaction time.
_checkLoanAvailable(loan);
// 2. Use the payment to cover accrued interest and reduce debt.
// The returned amounts are the interests paid and the principal component used to reduce debt only.
require(payment <= loan.amount.add(loan.accruedInterest), "Payment too high");
_processPayment(loan, payment);
// 3. Get the equivalent payment amount in sUSD, and also distinguish
// the fee that would be charged for both principal and interest.
(uint expectedAmount, uint exchangeFee, ) = _exchanger().getAmountsForExchange(payment, loan.currency, sUSD);
uint paymentSUSD = expectedAmount.add(exchangeFee);
// 4. Reduce the collateral by the equivalent (total) payment amount in sUSD,
// but add the fee instead of deducting it.
uint collateralToRemove = paymentSUSD.add(exchangeFee);
loan.collateral = loan.collateral.sub(collateralToRemove);
// 5. Pay exchange fees.
_payFees(exchangeFee, sUSD);
// 6. Burn sUSD held in the contract.
_synthsUSD().burn(address(this), collateralToRemove);
// 7. Update the last interaction time.
loan.lastInteraction = block.timestamp;
// 8. Emit the event for the collateral repayment.
emit LoanRepaymentMade(borrower, borrower, id, payment, loan.amount);
// 9. Return the amount repaid and the remaining collateral.
return (payment, loan.collateral);
}
function _closeWithCollateral(address borrower, uint id) internal returns (uint amount, uint collateral) {
// 0. Get the loan to repay and accrue interest.
Loan storage loan = _getLoanAndAccrueInterest(id, borrower);
// 1. Repay the loan with its collateral.
uint amountToRepay = loan.amount.add(loan.accruedInterest);
(amount, collateral) = _repayWithCollateral(borrower, id, amountToRepay);
// 2. Record loan as closed.
_recordLoanAsClosed(loan);
// 3. Emit the event for the loan closed by repayment.
emit LoanClosedByRepayment(borrower, id, amount, collateral);
// 4. Explicitely return the values.
return (amount, collateral);
}
}