Skip to content

Commit

Permalink
Update dynamic synth redeemer and issuer
Browse files Browse the repository at this point in the history
  • Loading branch information
barrasso committed Mar 28, 2024
1 parent f722caf commit a0ffdf8
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 190 deletions.
52 changes: 14 additions & 38 deletions contracts/DynamicSynthRedeemer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "./SafeDecimalMath.sol";
// Internal references
import "./interfaces/IERC20.sol";
import "./interfaces/IIssuer.sol";
import "./interfaces/IExchangeRates.sol";

contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {
using SafeDecimalMath for uint;
Expand All @@ -20,19 +21,19 @@ contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {

bytes32 public constant CONTRACT_NAME = "DynamicSynthRedeemer";

mapping(address => uint) public redemptions;

bytes32 private constant CONTRACT_ISSUER = "Issuer";
bytes32 private constant CONTRACT_SYNTHSUSD = "SynthsUSD";
bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";

constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {
_discountRate = SafeDecimalMath.unit();
}

function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
addresses = new bytes32[](2);
addresses = new bytes32[](3);
addresses[0] = CONTRACT_ISSUER;
addresses[1] = CONTRACT_SYNTHSUSD;
addresses[2] = CONTRACT_EXRATES;
}

function issuer() internal view returns (IIssuer) {
Expand All @@ -43,12 +44,8 @@ contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {
return IERC20(requireAndGetAddress(CONTRACT_SYNTHSUSD));
}

function totalSupply(IERC20 synthProxy) public view returns (uint supplyInsUSD) {
supplyInsUSD = synthProxy.totalSupply().multiplyDecimal(redemptions[address(synthProxy)]);
}

function balanceOf(IERC20 synthProxy, address account) external view returns (uint balanceInsUSD) {
balanceInsUSD = synthProxy.balanceOf(account).multiplyDecimal(redemptions[address(synthProxy)]);
function exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES));
}

function discountRate() external view returns (uint) {
Expand All @@ -61,25 +58,25 @@ contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {
emit DiscountRateUpdated(_discountRate);
}

function redeemAll(IERC20[] calldata synthProxies) external {
function redeemAll(IERC20[] calldata synthProxies, bytes32[] calldata currencyKeys) external {
for (uint i = 0; i < synthProxies.length; i++) {
_redeem(synthProxies[i], synthProxies[i].balanceOf(msg.sender));
_redeem(synthProxies[i], synthProxies[i].balanceOf(msg.sender), currencyKeys[i]);
}
}

function redeem(IERC20 synthProxy) external {
_redeem(synthProxy, synthProxy.balanceOf(msg.sender));
function redeem(IERC20 synthProxy, bytes32 currencyKey) external {
_redeem(synthProxy, synthProxy.balanceOf(msg.sender), currencyKey);
}

function redeemPartial(IERC20 synthProxy, uint amountOfSynth) external {
function redeemPartial(IERC20 synthProxy, uint amountOfSynth, bytes32 currencyKey) external {
// technically this check isn't necessary - Synth.burn would fail due to safe sub,
// but this is a useful error message to the user
require(synthProxy.balanceOf(msg.sender) >= amountOfSynth, "Insufficient balance");
_redeem(synthProxy, amountOfSynth);
_redeem(synthProxy, amountOfSynth, currencyKey);
}

function _redeem(IERC20 synthProxy, uint amountOfSynth) internal {
uint rateToRedeem = redemptions[address(synthProxy)];
function _redeem(IERC20 synthProxy, uint amountOfSynth, bytes32 currencyKey) internal {
uint rateToRedeem = exchangeRates().rateForCurrency(currencyKey).multiplyDecimalRound(_discountRate);
require(rateToRedeem > 0, "Synth not redeemable");
require(amountOfSynth > 0, "No balance of synth to redeem");
issuer().burnForRedemption(address(synthProxy), msg.sender, amountOfSynth);
Expand All @@ -88,27 +85,6 @@ contract DynamicSynthRedeemer is Owned, IDynamicSynthRedeemer, MixinResolver {
emit SynthRedeemed(address(synthProxy), msg.sender, amountOfSynth, amountInsUSD);
}

function deprecate(IERC20 synthProxy, uint rateToRedeem) external onlyIssuer {
address synthProxyAddress = address(synthProxy);
require(redemptions[synthProxyAddress] == 0, "Synth is already deprecated");
require(rateToRedeem > 0, "No rate for synth to redeem");
uint totalSynthSupply = synthProxy.totalSupply();
uint supplyInsUSD = totalSynthSupply.multiplyDecimal(rateToRedeem);
require(sUSD().balanceOf(address(this)) >= supplyInsUSD, "sUSD must first be supplied");
redemptions[synthProxyAddress] = rateToRedeem;
emit SynthDeprecated(address(synthProxy), rateToRedeem, totalSynthSupply, supplyInsUSD);
}

function requireOnlyIssuer() internal view {
require(msg.sender == address(issuer()), "Restricted to Issuer contract");
}

modifier onlyIssuer() {
requireOnlyIssuer();
_;
}

event DiscountRateUpdated(uint discountRate);
event SynthRedeemed(address synth, address account, uint amountOfSynth, uint amountInsUSD);
event SynthDeprecated(address synth, uint rateToRedeem, uint totalSynthSupply, uint supplyInsUSD);
}
Loading

0 comments on commit a0ffdf8

Please sign in to comment.