Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decentralized oracles with Chainlink #293

justinjmoses opened this issue Oct 23, 2019 · 12 comments

Decentralized oracles with Chainlink #293

justinjmoses opened this issue Oct 23, 2019 · 12 comments


Copy link

@justinjmoses justinjmoses commented Oct 23, 2019


The current Synthetix (SNX) oracle is a centralized point of failure. It runs constantly, reading in prices from a range of real-world pricing services and updates the ExchangeRates contract (currently at 0x99a46c4 at this time) with the latest prices for all of the assets underlying each of our synths (priced in USD).

The code for the SNX oracle is closed-source and centralized. It is closed in order to prevent bots from calculating differences in prices off-chain and profiting from delays in Ethereum transaction latency. It is centralized and managed by the Synthetix team, and while vigorously monitored and maintained, has significant centralization risk, with users forced to trust the team, their processes and integrity.


To migrate to a decentralized oracle solution for all of our synths. The most robust solution available with the highest level of community engagement is the Chainlink ecosystem of pricing networks.

We propose to enter into agreement with Chainlink, upgrading our ExchangeRates contract to using their pricing networks gradually.

However, in order to prevent front-running of decentralized oracle prices, there is a strict dependency on Synthetix first refactoring the exchange() functionality to a new queuing mechanism (more details below).


The Chainlink ecosystem uses certain language around oracles and pricing that makes sense to incorporate into the Synthetix nomenclature.

  • An oracle is an instance of their Oracle contract that supplies a price for a single asset (ETHUSD, BTCUSD or AUDUSD say). Each oracle is supported by a node on the backend, who is paid in LINK for their services.
  • An aggregator is an instance of their Aggregator contract which aggregates requests to all oracles in its list, yielding a single aggregate price (the public property currentAnswer is the price multiplied by some power of 10 for decimal support) for the asset.
  • A network is a collection of oracles that provide the same price. It is served by a single Aggregator that can be read on-chain

For example, here is a visualization of the ETHUSD aggregation network:


  • It is a single network that provides the ETHUSD price
  • There are currently 19 oracles serving the network.
  • And, there is a single Aggregator contract which aggregates these oracles on-chain, yielding a single readable price for ETHUSD: 0x79febf6. The current price is Aggregator.currentAnswer (which is the current market price of ETHUSD multiplied by 1e8 for decimal support). The last block number used for any oracle update is updatedHeight. As per the contract's minimumResponses property, only when 14 oracles have returned a price for a request will the Aggregator update the currentAnswer and updatedHeight.


To work with the Chainlink ecosystem, our ExchangeRates contract would need to be refactored.

Unlike our current oracle which pushes multiple prices updates simultaneously, Chainlink uses a one-price-per-contract approach for modularity and reuse purposes. We agree with this approach, though some light refactoring will be required so that our ExchangeRates contract knows where to find the price for each synth. It will need a mapping of synth keys to a Chainlink Aggregator for that pricing network (e.g. mapping(bytes32=>address)).

For inverted synths - such as iETH, iBTC et al - we propose reading the regular rate from the Aggregator and then inverting it in our ExchangeRates contract, as we do currently.

Cost Basis

Currently the Synthetix Foundation is paying both the API costs for real world pricing of assets and the gas costs of updating the ExchangeRates contract on-chain.

Moving towards decentralized oracles will offload these costs from Synthetix directly. Synthetix and Chainlink are working together to find a reasonable cost basis for ongoing upkeep of the various pricing networks for all synthetic assets used.


Pricing networks

Since inception, Synthetix has been fairly flexible with trying out different synths. This will be marginally more difficult under a decentralized system as a price network needs to form and be available on mainnet for every new synth added to the ecosystem. This will mean more lead time for adding new synths to the system.

Index synths

For indexed synths - such as sCEX and the upcoming sDEFI which are a weighted basket of number of prices - we propose working with Chainlink nodes to do the weighted calculations off-chain and provide the pricing of our indexes on-chain directly. The alternative would be a pricing network for every price inside each index (if it didn't exist already), which would be too costly.



The current Synthetix system tackles front-running of SNX oracle updates by limiting how much Gwei an exchange can be performed with (see SIP-12). This works as the centralized SNX oracle can be guaranteed to ensure all oracle updates are performed with higher Gwei than the aforementioned limit.

With Chainlink's network of decentralized oracles, this cannot be guaranteed. However with a large number of oracles per price network, and the Aggregator taking the median of a minimum number of updates, front running a price network becomes marginally more complex.

Frequency of updates

The SNX oracle runs regularly and updates prices on-chain, ensuring that small price movements are tracked. If an on-chain price deviates by more than the current exchange fee (currently 0.5% but lowering back to 0.3% soon), we update it, preventing bots from taking advantage of the difference between on-chain and real-world pricing (what we refer to as "technical front-running"). Morever, the SNX oracle ensures that every price is updated at least once an hour - and if any price is more than 3 hours stale (configurable via ExchangeRates.rateStalePeriod), the system freezes.

Chainlink's pricing networks will target on a 1% price deviation and a heartbeat of approximately twice a day. While the slower heartbeat can be incorporated into our system, the larger price deviation would expose the system to an unacceptable amount of "technical front-running".


Thus, in order to migrate to the decentralized oracle system of Chainlink and not expose the system to front-running attacks mentioned above, a different mechanism of exchanging is required. What we propose is to overhaul the exchange() functionality inside Synthetix. Instead of exchanges happening immediately, they would be placed into a queue to be processed FIFO once prices for both the source and destination synths has been received. This introduces its own challenges (such as who pays the gas), but has the added benefit of supporting limit orders on-chain.

This queuing mechanism will be a prerequisite to migrating to a decentralized oracle service. Once applied, we can begin the transition to Chainlink's pricing networks, one synth at a time.

@justinjmoses justinjmoses pinned this issue Oct 23, 2019
@justinjmoses justinjmoses changed the title Migrate to Chainlink's decentralized oracles Decentralized oracles with Chainlink Oct 23, 2019
Copy link

@CryptoToit CryptoToit commented Oct 23, 2019

Hey Justin, great write up!

Couple questions:
1- Which "Price Networks (PN)" are currently available from the ChainLink network?
2- Do you have an available list?
3- Does these cover our current list of Synths?
4- If not, what would it take to 'get' a new PN up and running? It seems that it would require at least 14 independent nodes contributing to a specific PN.

My concern wrt the questions above is that we end up with 70% of Synths reading price from the ChainLink network and still have to sit with a centralised Oracle for years. I'm thinking of when we start getting to synths like AAPL, MSFT, FB, GOOGL etc.

I do however agree and like the phased approach of migrating specific synths over one at a time.


Copy link
Member Author

@justinjmoses justinjmoses commented Oct 23, 2019

Hey @CryptoToit,

  1. Right now only ETHUSD AFAIK, though other crypto markets are on the way
  2. No I don't, but perhaps @JohannEid can chime in?
  3. No they don't, but Chainlink are aware of SNX needs and are working towards them
  4. A PN needs enough oracles to be be "secure" - i.e. how many nodes does an attacker need to be compromised in order to significantly impact the price? If the minimum number of oracles is 7 then the answer is 4, if 5 then 3 (the majority). We're going to work with Chainlink and their nodes to decide on the right minimum of oracles needed per price together.

You're right to be concerned about a continued dependency on the centralized SNX oracle, yet both teams want to see the end of the SNX oracle sooner rather than later. We won't consider the SNX platform decentralized and derisked until all prices are sourced from decentralized on-chain oracles.

Copy link

@JohannEid JohannEid commented Oct 23, 2019

Hey @CryptoToit , @justinjmoses answered most of the points.
Concerning the price feeds, we currently have ETH/USD on mainnet and will be putting new ones first on testnet then mainnet in the very near future. The process for Chainlnik to put new PN(price networks) on mainnet is extremely straightforward and we're confident that we'll be able to answer all of Synthetix's oracles needs in a timely manner.

You can keep yourself updated by following this page

As for the node operators who're responsible to provide data to these PNs, we already have more then 80+ listed here including 20 highly reliable blockchain infrastructure companies.

Copy link

@iblockchain iblockchain commented Oct 31, 2019

Decentralized Oracle make no sense if without data source diversity,20+ oracle nodes get data input from only limited data source.
And especially important official data,such as stock price,game results,weather data, the data source is almost just one,and centralized oracle is more efficient than decentralized oracle( the all nodes get input from the same one source).

Copy link

@ChainLinkGod ChainLinkGod commented Oct 31, 2019

@iblockchain I agree this is legitimate concern for oracle feeds, but Chainlink Oracle networks support both decentralization at both the oracle operator level and the data source level. For example the ETH/USD Heartbeat ( currently pulls the ETH price from BraveNewCoin, CoinMarketCap, CryptoCompare, Kaiko, and I think a few other sources as well. Each Oracle delivers their data from their respective source to Ethereum and the median is taken (or any other aggregation method) on-chain (eventually off-chain through Threshold Signatures).

Copy link

@JohannEid JohannEid commented Nov 2, 2019

@ChainLinkGod exactly the right answer. Just for your information, the nodes on ETH/USD network are also pulling data from Coinpaprika, Coingecko, CoinAPI and CoinCap, making it a total of 8 different data providers. We plan to bring the same focus on decentralization to Synthetix's price feeds.

Copy link

@Arthur0x Arthur0x commented Nov 9, 2019

How often is the Chainlink oracle for ETHUSD updated at current implementation? My biggest concern is the frequency of updates. Even the current Synthetix oracle arguably doesn't update the price frequent enough especially when compare to an off-chain orderbook onchain settlement DEX protocol like 0x or Loopring.

In a day where market doesn't move much and the Chainlink oracle is only updated once every 30 mins, the user experience of Synthetix Exchange will be severely impacted especially when combined with our Exchange queuing proposal. A trade order might not be executed for a long time, this essentially make a market order on Synthetix impossible.

Copy link

@JohannEid JohannEid commented Nov 11, 2019

Hey @Arthur0x - thank you for your comment. We plan to update the price at every 1% deviation. The way it will work is by having an off-chain component called the "flux monitor" which will ping a price API every minute. If it ever sees a 1% difference in price between the on-chain price and the current API price, it will trigger an update of the reference contract.

Copy link

@RewKang RewKang commented Nov 17, 2019

@JohannEid Who controls the flux monitor? Would it be considered a centralized source of risk?

Copy link

@JohannEid JohannEid commented Nov 20, 2019

Hey @RewKang , the intent is to have third party node operators all run their own flux monitor which will allow for a highly decentralized network without any central point of failure. For each node operators running, there will be another flux monitor up.

Copy link
Member Author

@justinjmoses justinjmoses commented Dec 2, 2019

Here is the proposal for phase one of the migration - commodity and forex synths:

Copy link

@dongzhuoyao dongzhuoyao commented Dec 10, 2020

Hey @Arthur0x - thank you for your comment. We plan to update the price at every 1% deviation. The way it will work is by having an off-chain component called the "flux monitor" which will ping a price API every minute. If it ever sees a 1% difference in price between the on-chain price and the current API price, it will trigger an update of the reference contract.

So you mean each minute, we will query the on-chain price, which will also introduce cost?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

8 participants