@@ -2,6 +2,7 @@ pragma solidity ^0.5.16;
2
2
3
3
// Inheritence
4
4
import "./Owned.sol " ;
5
+ import "./Proxyable.sol " ;
5
6
import "./MixinResolver.sol " ;
6
7
import "./interfaces/IDynamicSynthRedeemer.sol " ;
7
8
@@ -11,11 +12,6 @@ import "./SafeDecimalMath.sol";
11
12
// Internal references
12
13
import "./interfaces/IIssuer.sol " ;
13
14
import "./interfaces/IExchangeRates.sol " ;
14
- import "./interfaces/ISynth.sol " ;
15
-
16
- interface IProxy {
17
- function target () external view returns (address );
18
- }
19
15
20
16
contract DynamicSynthRedeemer is Owned , IDynamicSynthRedeemer , MixinResolver {
21
17
using SafeDecimalMath for uint ;
@@ -42,63 +38,79 @@ contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {
42
38
addresses[1 ] = CONTRACT_EXRATES;
43
39
}
44
40
45
- function issuer () internal view returns (IIssuer) {
41
+ /* ========== INTERNAL VIEWS ========== */
42
+
43
+ function _issuer () internal view returns (IIssuer) {
46
44
return IIssuer (requireAndGetAddress (CONTRACT_ISSUER));
47
45
}
48
46
49
- function exchangeRates () internal view returns (IExchangeRates) {
47
+ function _exchangeRates () internal view returns (IExchangeRates) {
50
48
return IExchangeRates (requireAndGetAddress (CONTRACT_EXRATES));
51
49
}
52
50
53
- function redeemingActive () internal view {
51
+ function _redeemingActive () internal view {
54
52
require (redemptionActive, "Redemption deactivated " );
55
53
}
56
54
57
- /* ========== VIEWS ========== */
55
+ /* ========== EXTERNAL VIEWS ========== */
58
56
59
57
function getDiscountRate () external view returns (uint ) {
60
58
return discountRate;
61
59
}
62
60
61
+ /* ========== INTERNAL HELPERS ========== */
62
+
63
+ function _proxyAddressForKey (bytes32 currencyKey ) internal returns (address ) {
64
+ address synth = address (_issuer ().synths (currencyKey));
65
+ require (synth != address (0 ), "Invalid synth " );
66
+ return address (Proxyable (synth).proxy ());
67
+ }
68
+
63
69
/* ========== MUTATIVE FUNCTIONS ========== */
64
70
65
- function redeemAll (address [] calldata synthProxies ) external requireRedemptionActive {
66
- for (uint i = 0 ; i < synthProxies.length ; i++ ) {
67
- _redeem (synthProxies[i], IERC20 (synthProxies[i]).balanceOf (msg .sender ));
71
+ function redeemAll (bytes32 [] calldata currencyKeys ) external requireRedemptionActive {
72
+ for (uint i = 0 ; i < currencyKeys.length ; i++ ) {
73
+ address synthProxy = _proxyAddressForKey (currencyKeys[i]);
74
+ _redeem (synthProxy, currencyKeys[i], IERC20 (synthProxy).balanceOf (msg .sender ));
68
75
}
69
76
}
70
77
71
- function redeem (address synthProxy ) external requireRedemptionActive {
72
- _redeem (synthProxy, IERC20 (synthProxy).balanceOf (msg .sender ));
78
+ function redeem (bytes32 currencyKey ) external requireRedemptionActive {
79
+ address synthProxy = _proxyAddressForKey (currencyKey);
80
+ _redeem (synthProxy, currencyKey, IERC20 (synthProxy).balanceOf (msg .sender ));
73
81
}
74
82
75
- function redeemPartial (address synthProxy , uint amountOfSynth ) external requireRedemptionActive {
83
+ function redeemPartial (bytes32 currencyKey , uint amountOfSynth ) external requireRedemptionActive {
84
+ address synthProxy = _proxyAddressForKey (currencyKey);
76
85
// technically this check isn't necessary - Synth.burn would fail due to safe sub,
77
86
// but this is a useful error message to the user
78
87
require (IERC20 (synthProxy).balanceOf (msg .sender ) >= amountOfSynth, "Insufficient balance " );
79
- _redeem (synthProxy, amountOfSynth);
88
+ _redeem (synthProxy, currencyKey, amountOfSynth);
80
89
}
81
90
82
- function _redeem (address synthProxy , uint amountOfSynth ) internal {
83
- bytes32 currencyKey = ISynth (IProxy (synthProxy).target ()).currencyKey ();
91
+ function _redeem (
92
+ address synthProxy ,
93
+ bytes32 currencyKey ,
94
+ uint amountOfSynth
95
+ ) internal {
96
+ require (amountOfSynth > 0 , "No balance of synth to redeem " );
84
97
require (currencyKey != sUSD, "Cannot redeem sUSD " );
85
98
86
99
// Discount rate applied to chainlink price for dynamic redemptions
87
- uint rateToRedeem = exchangeRates ().rateForCurrency (currencyKey). multiplyDecimalRound (discountRate );
88
- require ( rateToRedeem > 0 , " Synth not redeemable " );
89
- require (amountOfSynth > 0 , "No balance of synth to redeem " );
100
+ ( uint rate , bool invalid ) = _exchangeRates ().rateAndInvalid (currencyKey);
101
+ uint rateToRedeem = rate. multiplyDecimalRound (discountRate );
102
+ require (rateToRedeem > 0 && ! invalid , "Synth not redeemable " );
90
103
91
- issuer ().burnForRedemption (address (synthProxy), msg .sender , amountOfSynth);
92
104
uint amountInsUSD = amountOfSynth.multiplyDecimalRound (rateToRedeem);
93
- issuer ().issueSynthsWithoutDebt (sUSD, msg .sender , amountInsUSD);
105
+ _issuer ().burnAndIssueSynthsWithoutDebtCache ( msg .sender , currencyKey, amountOfSynth , amountInsUSD);
94
106
95
- emit SynthRedeemed (address ( synthProxy) , msg .sender , amountOfSynth, amountInsUSD);
107
+ emit SynthRedeemed (synthProxy, msg .sender , amountOfSynth, amountInsUSD);
96
108
}
97
109
98
110
/* ========== MODIFIERS ========== */
99
111
100
112
modifier requireRedemptionActive () {
101
- redeemingActive ();
113
+ _redeemingActive ();
102
114
_;
103
115
}
104
116
0 commit comments