Terra’s mainnet will be upgraded to Columbus-3 on Friday, 13 December at block 2,530,000. There will be various major chain parameter changes as well as the new requirement for all validators to run price feed oracles reporting on the exchange rate of all of the whitelisted currencies in order to receive seigniorage rewards.
Validators who fail to submit a threshold amount of valid oracle votes over a time window will be slashed 0.01% of their stake. The Oracle Module in Columbus-3 sets the time window at 432,000 blocks and the minimum required valid votes per time window at 5%. A valid oracle vote is one that is within a 7% range of the last agreed weighted (by stake) median price from all valid oracle votes (median price - 3.5% ≤ price ≤ median price + 3.5%).
Given the amount of money at stake, we decided to implement our own oracle program, `oracle-voter` and open it for the community to use and study.
The Role of Oracles
Oracles are verified providers that make data from the real world available for use on the blockchain. They are required because nodes within a blockchain are unable to verify and retrieve all off-chain data in a safe manner.
For the context of Terra, oracles fulfill the function of price discovery for the whitelisted currencies on the network, namely Korean Won (KRW), US Dollar (USD), Mongolian Tugrik (MNT) and the IMF Special Drawing Rights basket (SDR).
Terra validators serve as oracles that report on the various exchange rates of LUNA against the above 4 currencies. The US Dollar and LUNA rate is denominated as uluna <> uusd. All prices are quoted in micro denominations (10e^-6), 1 million uusd = 1 USD. For example, to submit a vote for the exchange rate of LUNA against the US Dollar, the validator through the oracle would vote `1uusd` for the uluna <> 1 uusd pair.
The voting process occurs in two stages: a prevote followed by a vote, wherein oracles submit a `MsgExchangePreVote` and `MsgExchangeVote` respectively. This is to prevent free-rider risk and centralization, where validators observe each other’s prices before voting for a price.
In the prevote stage, validators select a random salt of not more than 4 characters, and produce a SHA256 hash of the following payload: `salt:exchange_rate:denom:voter`. The first 20 bytes of the SHA256 hash is submitted to the chain via the transaction with message type `MsgExchangeRatePreVote`.
In the voting stage, validators must reveal the `salt` used to generate the hash submitted in the previous `VotePeriod`, as well as the exchange rate for currency pair. The chain verifies that the hash of the payload submitted at t against the submitted hash in `VotePeriod` t-1. If the verification succeeds, the validator’s vote is included for tallying of the on-chain exchange rate and the on-chain exchange rate is updated once when the tally is reached.
Our oracle-voter program consists of 3 parts: Feeds, Pricing and Voting.
Our oracle uses `Coinone` exchange and `UKFX` for LUNA/KRW and the FX pairs MNT/KRW, USD/KRW and SDR/KRW respectively. During each new `VotePeriod`, the oracle grabs orderbook data from `Coinone` and the last traded price from `UKFX` and feeds it as inputs into the pricing model, described below. If the oracle is unable to get a response from any of the data providers, the oracle will submit an `Abstain` vote by setting the price at `-1.000`.
We use a modification of the microprice model which is the weighted mid price based on the current open order volumes on the bid and ask of the orderbook. Calculation for the microprice is as follows:
When the volumes posted on the ask side of the orderbook is greater than the volumes posted on the bid side of the orderbook, the microprice is shifted closer to the best ask available on the orderbook. The microprice serves as a good approximation to the relative liquidity available at present on the orderbook and also as an estimator for future mid prices.
We also include price deviation checks into the oracle to prevent the voted prices from drifting too far from the last known on chain exchange rate. This is set arbitrarily at 2%, and will be re-evaluated regularly.
At the start of each `VotePeriod`, the oracle queries the current list of prevotes for the validator for each whitelisted currency. If there was a previous prevote for the currency, the oracle checks if the salt and related information is in memory. If so, it will then submit a single transaction containing multiple votes, one for each of the whitelisted currencies.
The sequence must be `PreVote -> Vote -> PreVote -> Vote`, otherwise the node will return an error. Multiple `PreVote` transactions are allowed with the latest transaction overwriting the previous one. Multiple prices are allowed in a single transaction, hence we batch all voting for white-listed currencies into 2 transactions: 1 for prevote and 1 for vote.
Between `VotePeriod`s, the oracle queries for the success / failure of the transactions previously submitted and keeps tabs on them in memory.
We would like to give a big thanks to the B-Harvest team for the code inspiration from their oracle script. We will be adding more features (for e.g, price feed coming from more exchanges) and tests to improve coverage as we go along, so feel free to ping us if you find any issues!
Last but not least, some good reads for the curious minds on decentralized oracles:
- Comprehensive Overview on Decentralized Oracles by Julien Thevenard from Fabric Ventures
- The Oracle Problem by Alexander Egberts
- Oracle Oracle What’s the Right Price by Marco Di Maggio
StakeWith.Us is a secure Staking Infrastructure Provider for leading blockchain projects. We are backed by SGInnovate, the Singapore Government’s Deep Tech Fund and LuneX Ventures, Golden Gate Ventures’s blockchain arm.
Lastly, subscribe to our monthly Staker Digest updates if you want to learn more about our staking projects!
Alternatively, reach out to Earn@StakeWith.Us if:
- you have any burning queries for us;
- you are a project looking for a professional validator;
- you are looking into investment and partnership opportunities with StakeWith.Us.