SIP-2059: Legacy Spot Synth Migration

NetworkEthereum & Optimism
ImplementorMEB (@barrasso)
ProposalLoading status...

Simple Summary

The SIP proposes deprecating classic exchanges (and atomic exchanges) of all non sUSD synths, in favor of a new redeemer contract that redeems users at the Chainlink price multiplied by a discountRate. This discountRate would start at 1 and could decrease gradually according to a pre-approved schedule that can be voted on by governance with an SCCP.


After this SIP is implemented, users holding synths will only be able to redeem them to sUSD at the Chainlink price multiplied by the specified discount factor.


The legacy spot synths are overutilized relative to their value to stakers; they generate minimal revenue and incur significant hedging costs for stakers. Spot synths in V3 have been redesigned to be more aligned with the interests of stakers. This proposal will immediately begin to reduce the debt pool skew and the costs associated with stakers managing their debt hedging due to changes in the composition of outstanding synths. It also prepares for the migration of debt to V3 later in the year as new products are launched, including the upcoming L1 ETH perp.


  • Suspend existing exchange functionality via SystemStatus.suspendSynthsExchange.

  • Create a new redeemer contract DynamicSynthRedeemer that allows users to redeem synths for chainlink price * discountRate. The contract adjusts redemption prices based on Chainlink price data at the time of execution (as opposed to SIP-174: Synth Redeemer, which does so at a fixed rate).

  • Update DebtCache to take the discountRate into account for its issued synth reporting:

    function _issuedSynthValues(
        bytes32[] memory currencyKeys,
        uint[] memory rates
    ) internal view returns (uint[] memory values) {
        uint numValues = currencyKeys.length;
        values = new uint[](numValues);
        ISynth[] memory synths = issuer().getSynths(currencyKeys);

        for (uint i = 0; i < numValues; i++) {
            address synthAddress = address(synths[i]);
            require(synthAddress != address(0), "Synth does not exist");
            uint supply = IERC20(synthAddress).totalSupply();
            uint value = supply.multiplyDecimalRound(rates[i]);
            values[i] = value.multiplyDecimalRound(dynamicSynthRedeemer().discountRate());

        return (values);

Test Cases

Unit Tests

For DynamicSynthRedeemer:

  • It only allows owner to update discountRate.
  • It reverts if synth is not up for redemption.
  • It reverts if the sender does not have enough synth balance.
  • It applies the expected discountRate to the redemption price.
  • It correctly updates synth balances.

Integration Tests

A integration test to cover the dynamic redemptions.

  • Verify synth exchanging is suspended.
  • Verify the caller has enough synth balance.
  • Verify it burns the correct amount of synths from the caller.
  • Verify it returns the correct amount of sUSD to the caller.
  • Verify the total issued synth values are correctly reported.
  • Verify it emits a SynthRedeemed event with the expected values.

Manual Tests

  • Deploy and test on sepolia and sepolia-ovm.
  • Confirm discountRate is applied to the aggregator price on redemption.
  • Confirm debt value is reported as expected by debt oracle.

Configurable Values (Via SCCP)

The discountRate that allows configuration of the funding rate imposed on holding volatile synths on L1.

Copyright and related rights waived via CC0.