New Exchange Rate Mechanism

Summary

We propose to replace the existing proposal-based ICP/XDR conversion rate mechanism with an exchange rate canister that makes use of the forthcoming HTTP call feature.
The new mechanism not only improves decentralization but also provides a more general service, offering current exchange rates for arbitrary cryptocurrency and fiat currency pairs.

Status

Discussing

Key people involved

David Ribeiro Alves, Ryan Croote, Yotam Harchol, Thomas Locher

Description

Since the price of cycles is pegged to the IMF SDR and cycles are obtained by burning ICP, the NNS has to know the current ICP/XDR rate at all times.

The current mechanism uses “conversion rate providers”, which periodically fetch pricing information from market data providers and exchanges and then create NNS proposals to update the conversion rate.

While it is a fairly safe mechanism, it has several shortcomings:

  • Everybody could generate such proposals in theory but there is little incentive to do so. As a result, the whole mechanism is controlled by DFINITY, which means it is not a (fully) decentralized mechanism.
  • The NNS needs to deal with a large number of conversion rate proposals daily. As the market sets the conversion rate, there shouldn’t be a need to further vote on it.
  • DFINITY needs to make sure that the conversion rate providers are always running and be ready to step in whenever there are issues.

We propose to replace this mechanism with an entirely different mechanism based on the HTTP call feature.
The main component of the new mechanism is an exchange rate canister that queries market data providers and exchanges, using HTTP calls, in order to reply to exchange rate request from other canisters.
For example, the cycle minting canister will periodically request the ICP/XDR conversion rate from the exchange rate canister.

We believe that being able to reliably retrieve exchange rates will also benefit a range of other services developed by the community.

Next Steps

The first step is to get feedback and input from the community here in the forum.
There will be a community conversation about this topic, tentatively scheduled for August 18, 2022.
After the community conversation, a motion proposal will be issued. If the proposal is accepted, development will start soon thereafter.

31 Likes

This is a perfect first use case of the new HTTP request feature!

Which API are you calling to get the pricing data though? Will this be made public?

4 Likes

We will likely use historical candlestick data, aggregated over a one-minute interval, in order to ensure deterministic responses.
This type of information can be obtained from most exchanges.

And yes, the whole exchange rate canister will be open-sourced!

6 Likes

Perfect use of the HTTPS feature. Will the update rate be the same as the current exchange rate canister?

3 Likes

A requested exchange rate will be fetched on demand, so there is no fixed update rate.

The ICP/XDR rate will probably be an exception because we know that the cycle minting canister will request it periodically. There is no decision yet on the update rate but we could certainly update it more frequently than once every ten minutes as it is done now.

4 Likes

team, come and join community conversation on August 18, 2022: Live Sessions | Internet Computer Home

2 Likes

Thanks to everyone who joined the community conversation!

Here is a summary of the current feature design.
Note that the design reflects our current thinking and it is possible that some parts of the design will change.

NNS Proposal: New Exchange Rate Mechanism

The goal is to replace the current ICP/XDR conversion rate mechanism with a more general, decentralized mechanism based on an exchange rate canister that will be developed if the motion proposal is accepted.

The exchange rate canister, running in a system subnet, will enable any canister to request the exchange rate between any pair of fiat currency and cryptocurrency - including pairs of fiat currencies and pairs of cryptocurrencies. It will further be possible to request rates in the recent past.

Design

The main component of the proposed feature is the exchange rate canister. This canister will make use of the new HTTP call feature to obtain FOREX and cryptocurrency exchange rates from numerous public sources.
The exchange rate canister will offer (at least) the following endpoint:

get_exchange_rate(base_asset: String, quote_asset: String, timestamp: opt u64) -> (ExchangeRateResult);

The base and quote assets can be arbitrary currency codes. If no rate can be obtained for either asset, for the current time or the specified timestamp, an error is returned with an error message.
If an exchange rate could be computed, the returned results contains the rate as well as metadata such as the number of data sources that provided rates, the spread among the rates, among other information.

Invoking this function will cost cycles but the exact amount has yet to be determined.

4 Likes

Proposal is live: https://dashboard.internetcomputer.org/proposal/76767

1 Like

How do you mange the risk of your data sources going down or being taken down? Are we dependent on an emergency proposal being adopted to get us out of a hole? Could an attacker target this mechanism?

I generally wary of remote data sources becoming dependencies.

Can we keep the existing system in place in case we need it?

2 Likes

@THLO It would be helpful to first receive an complete overview of what the current exchange mechanism looks like, something that would show all the dependencies, and maybe a flow chart/diagram to show how the exchange/price data coming from source X ends up affecting the cycles exchange rate.

From the proposal, it mentions an exchange rate canister:

“The exchange rate canister, running in a system subnet, will enable any canister to request the exchange rate between any pair of fiat currency and cryptocurrency - including pairs of fiat currencies and pairs of cryptocurrencies. It will further be possible to request rates in the recent past.”

@diegop A few follow-up questions.

  1. The proposal mentions that it will be possible to request rates in the “recent past” - how far back is the recent past? How far back, as well as the update interval has significant implications with respect to how much data might be stored in the canister.

  2. I understand the importance of this feature in terms of ICP/USD, but why is DFINITY developing and owning an exchange rate canister that will keep track of all other currencies? That puts a lot of trust and eyes on this specific exchange rate canister.

  3. Why does it make sense for DFINITY to go beyond ICP/USD and to build the tooling for what could become a cryptocurrency exchange on the IC? Does DFINITY have plans to build their own DeFi ecosystem?

2 Likes

to be perfectly honest, I submitted it on behalf of R&D, but I am not the right person to ask. @THLO is better suited.

1 Like

Thanks a lot for your questions! Let me try to answer all of them.

How do you manage the risk of your data sources going down or being taken down? Are we dependent on an emergency proposal being adopted to get us out of a hole? Could an attacker target this mechanism?

We already have this risk in the current mechanism: Our conversion rate providers periodically query data from exchanges and market data providers. Since there is a lot of redundancy (every source is queried every time), an attacker would have to take down or corrupt many data sources. More precisely, the conversion rate providers currently get the ICP/USD rate from 7 different exchanges and select the median rate. They further query 3 market data providers to get the current USD/XDR rate and again select the median rate. We currently have paid subscriptions for the USD/XDR sources, so a lower number of sources is deemed acceptable.
Since we will only make use of (free) public sources in the new mechanism, we plan to query Forex data from numerous (more than 3!) sources.

In short, targeting the new mechanism won’t be easier than targeting the current mechanism.
It is correct that we have to monitor the process and create a proposal to upgrade the canister if we want to add or remove data sources.

It would be helpful to first receive an complete overview of what the current exchange mechanism looks like

Once the median rates are selected as described above, the two rates are multiplied to obtain the current ICP/XDR rate. Using a round-robin mechanism, one of the conversion rate providers creates a proposal and the others simply vote, accepting the proposal if the proposed rate does not deviate much (at most 1%) from the locally computed rate.
That’s the mechanism in a nutshell. If you think it would help, I can post a diagram and add more details.

The proposal mentions that it will be possible to request rates in the “recent past” - how far back is the recent past?

The idea is to store the daily Forex rates (one data point for each supported fiat currency) for some time, possibly one year. In this case, the amount of data that needs to be stored is 365 times the number of fiat currencies times the size of the rate data structure.

Note that cryptocurrency rates are queried on demand, so the canister only stores very little data.

why is DFINITY developing and owning an exchange rate canister that will keep track of all other currencies?

As mentioned above, the exchange rate canister will not “keep track” of other currencies, it will merely provide an interface to query exchange rates. Developers are free to use the HTTP call feature directly.

Why does it make sense for DFINITY to go beyond ICP/USD and to build the tooling for what could become a cryptocurrency exchange on the IC? Does DFINITY have plans to build their own DeFi ecosystem?

It is not meant to become a cryptocurrency exchange. It simply offers a convenient way to access exchange rates. We could restrict it to just provide the ICP/XDR rate but we can get the functionality to query the rate for any currency pair basically for free.

It may appear that the exchange rate canister offers a lot but, in my view, it is just a generalization of the required system functionality to maintain the ICP/XDR rate (which will still be stored in the cycle minting canister).
DFINITY does not plan to build any applications on top.

6 Likes

Got it, thanks for the explanation.

If the exchange rate data is not kept and “cached” on the canister, could this open up the exchange rate canister to a cycle drain attack?

According to some initial feedback from DFINITY it looks like HTTP calls are expensive (400M cycles per call). Since the exchange rate canister would be the one paying for the HTTP calls, how do you plan on keeping it topped up and preventing cycle drain overuse?

3 Likes

First of all, the plan is to cache requested rates but only for a relatively short time (around one minute). So, when I said that “the canister only stores very little data”, I made the assumption that there won’t be too many requests for different rates simultaneously. In any case, there will be a maximum number of cached rates to bound the maximum canister state size.

The caching mechanism mainly serves to provide quick answers if the same rate was requested recently and to conserve bandwidth. A cycle drain attack won’t be possible because the exchange rate canister will run on a system subnet, i.e., it will be exempt from paying cycles.

4 Likes

Note that the pricing referred to here is provisional and pretty conservative (= expensive). We are currently working on an updated pricing model which will also determine the price for the HTTP outcalls feature and it is likely that it will become cheaper in this new model.

5 Likes

Will this be true for any canister that is deployed to a system subnet? Is it possible to have a canister on a system subnet that does pay cycles?

How this lazy loading can work in general? If I want to use the “free” exchange canister from an app subnet:

  1. Canister A requests an exchange rate in a query call which will fail first. Who should initiate the update call to load the data? And will the request fail again, after the cache expires?
  2. If the request should be an update call in the first place then cross subnet update call will be slower than a direct http call (data is heavily cached on exchange, takes just a few milliseconds) because 2 subnets need to finalize instead of one.
1 Like

Enabling/Disabling cycles accounting is a subnet-type wide setting, so (at least at the moment) it is not possible to have a canister that consumes cycles on a (currently only one, but we could have more) system subnet.

To see how it works in practice, you can run your local replica in system mode as well. Here are the lines to configure it that way.

5 Likes

The exchange rate canister will charge cycles for its service.
While it just makes sense to pay the canister for its service, it is further an effective mechanism to prevent spam.

Since we currently don’t support cross-subnet query calls, the plan is to use update calls for the time being.

You are right, these calls may be quite a bit slower than using the HTTP call API directly. There is a trade-off: If you use the exchange rate canister, you get a rate derived from inputs from many sources, so the effort to get accurate rates is low. However, you have to accept a higher latency. On the other hand, if you use the HTTP call functionality, the latency will be lower but you need to implement (and maintain) the code to compute accurate rates yourself.

4 Likes

Thanks, makes sense, I didn’t consider the multi exchange scenario (however such aggregation services probably already exists).

IF cross-subnet query calls would be possible

  • what would be the flow?
  • the canister would be designed to use that?

With the http request feature in theory it is possible to make a query call (via http) to another subnet, right? Of course strictly until the official way became supported :slight_smile:

1 Like