SIP-56: Differential Fees
Author | |
---|---|
Status | Implemented |
Type | Governance |
Network | Ethereum |
Implementor | TBD |
Release | TBD |
Created | 2020-05-01 |
Simple Summary
Ability for the protocol DAO to configure different exchange fee rates for each Synth
.
Abstract
Currently there is one universal exchange rate for exchanging synths which is set onchain in the FeePool
.
Upgrading the FeePool
to allow an array of Synths exchange rates to be set allowing unique pricing per asset or class.
There could be multiple pricing options TBD such as;
- Charge the fee rate of the synth being exchanged into.
Charge the sum of the pair.Charge the lowest of the pair.
UPDATE: The proposed pricing method is 1.
Motivation
With a universal exchange fee rate the protocol is limited in its ability to price markets fairly or apply incentive mechanisms. To deter front runners setting a high exchange rate was used to reduce profiitability affecting all Synth markets and discouraging good actors from trading.
Unique pricing per synth would allow potential outcomes such as;
a) Different price categories such as fiat, crypto, inverse, indices, commodities or stocks.
b) Used as a configurable protocol mechanism via SCCP to increase rates to deter new trades exchanging into a synth where there is an oversupply or potential debt risk to the system.
c) Configure a synth's exchange rate such as sUSD as low as possible to encourage traders to move into it or for SNX stakers to return to sUSD at no cost to be able to burn it to maintain the systems target c-ratio.
Specification
Storage of the rates should use the uint mappings
in the FeePoolEternalStorage
contract so FeePool
logic can be upgraded maintaining the exchange fee rate state.
New functions required in the upgradable FeePool
contract.
setExchangeFeeRateForSynths
Will allow the protocol DAO to set n number of exchangeFeeRates for n number of synths in one transaction.
Function signature
setExchangeFeeRateForSynths(bytes32[] synthKeys, uint256[] exchangeFeeRates) onlyOwner
bytes32[] synthKeys
: The array of currencyKeys for the synths to setuint256[] exchangeFeeRates
: The array of rates
exchangeFeeRateForSynth
Return the exchange fee rate for a synth
Function signature
exchangeFeeRateForSynth(bytes32 synth) public view returns (uint)
bytes32 synth
: synth key to request the rate for
deleteExchangeFeeRateForSynths (optional)
Will allow the protocol DAO to delete n number of synth rate entries freeing up the storage of removed / deprecated synths
Function signature
deleteExchangeFeeRateForSynths(bytes32 [synthKeys]) onlyOwner
bytes32 [synthKeys]
: The array of currencyKeys for the synths to delete
New functions required in the upgradable Exchanger
contract.
exchangeFeeForTrade
Returns the exchange fee in sUSD.
Deprecate existing fee view function FeePool.exchangeFeeIncurred(uint value) public view returns (uint)
and move to Exchanger.getAmountsForExchange
to accept the Synth trading pair as arguments to determine the exchange fee for the trade.
Function signature
getAmountsForExchange(uint sourceAmount, bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) public view returns (uint)
Parameters
uint sourceAmount
: Amount of the source Synth to exchangebytes32 sourceCurrencyKey
: Synth exchanging frombytes32 destinationCurrencyKey
: Synth to exchange into
Returns
uint amountReceived
: The amount recieved after exchange feesuint fee
: The fees payable for the exchangeuint exchangeFeeRate
: The exchange rate applied
Rationale
It was considered that a Synth
should store its own rate by having a setter for exchangeFeeRate
. However the rate storage would be lost on each upgrade and need to be reset again adding overhead to the upgrade process. Also each Synths external TokenState
is already immutable and not upgradable.
Test Cases
FeePool
- Given the pDAO needs to set multiple rates. When owner sends an array of x Synths and rates then store in the
FeePoolEternalStorage
on chain - Given the pDAO needs to set a single rate. When owner sends an array of x Synths and rates that are already stored then the synth rates are updated.
- Given the pDAO needs to update multiple rates. When owner sends an array of 1 Synths and rates then store in the
FeePoolEternalStorage
on chain - Given the pDAO needs to update 1 rate. When owner sends an array of 1 Synths and rates that are already stored then the synth rates are updated.
- Given a synthKey, anyone can view the exchange fee rates for the synthKey
- When owner sends a rate greater than MAX_EXCHANGE_FEE_RATE then revert
Exchanger
- Given I have a balance of Synth A and want to exchange into Synth B then I can view the
exchangeFeeRate
,fee
andamountReceived
- Given I exchange Synth A into Synth B and then the exchange fee rate applied should be the rate of Synth B
- Given I exchange into a Synth then the exchange rate is stored for fee reclaimation, when I return x seconds later and have a settlement owed to the debt pool or rebate owing to me the exchange fee rate at the time of my exchange is used for settlment and not the current rate in case it has changed.
Implementation
https://github.com/Synthetixio/synthetix/releases/tag/v2.22.4
Copyright
Copyright and related rights waived via CC0.