Sui

Simple and Meta

Oracles on Sui

Jul 28, 2023

Mysten Labs

6 min read

Oracles and their uses

Oracles in blockchains are fundamental utilities that enable smart contracts to connect to systems outside of the chain and execute based on real world data.

There are many types of contracts that could require oracles. For example, insurance contracts on future weather events may be used by farmers and holiday goers to hedge risk, but require access to real-time weather data to settle; a fantasy trading game could allow players to build a virtual portfolio of shares, and see their portfolio’s value grow (or get rekd) but requires real time access to share prices; prediction markets, that can crowdsource an estimate of the likelihood of geo-political events might require access to outcomes to be decided; a DeFi contracts could require accurate access to cryptocurrency relative prices in order to function properly.

These examples illustrate both the diversity of types of data that oracles may provide, as well as a wide variability in the assurance required to make oracle data useful – from lower for games to very high for contracts with high financial implications. This variability also affects the users’ willingness to pay for higher quality data, which may be low for data used in inconsequential low stakes games, and high for data used in contracts relating to DeFi.

A number of high-assurance oracles are now live on Sui – and we recommend using these for high assurance applications. However, the Mysten Labs team built a “simple oracle” that allows lower assurance values to be posted and read by contracts at a much cheaper gas cost point. We also illustrate a flexible way to combine oracle values from different sources using a “meta oracle” to achieve higher assurance, determined by the developer of the smart contract using the oracle. These oracles showcase the advantages of using native features of Sui to keep costs and complexity down and performance up: from native authentication, tables, and PTBs to read-only shared objects.

The simple oracle – a weak primitive

A simple oracle publishes a data stream. Each data item has some standard metadata such as a ticker symbol, a sequence number, a timestamp, and a reading identifier, as well as the actual value of the data item. The oracle is represented on-chain as a shared object that contains a table with data values, including the latest value and historical values that were archived.

Updating the oracle or archiving values are operations gated to only be authorized by a single authority that publishes the oracles. Currently, this access control relies on checking the update transaction address, but in the future we could extend this to use capabilities to increase flexibility. Multiple updates to multiple oracles from the same authority may be bundled together into a single Programmable Transaction Block (PTB). This results in a very economical operation: as an illustration we can update 30 values every 5 seconds only using 1843600 units of gas (MIST) or 0.0018436 SUI per on-chain transaction.

In order to read historical values provided by an oracle, a contract must take the shared object by reference and only read it. This use of a shared object in read-only mode is extremely efficient, as it does not induce contention, and all transaction reading values are executed in parallel in the Sui execution engine. The operation of reading a simple oracle value is extremely gas efficient as it only reads a dynamic field.

Anyone can run a simple oracle. In the spirit of permissionlessness and decentralization, organizations could coordinate off chain to determine a set of ticker symbols and conventions and independently begin emitting values for these data types. Other oracle operators could start operating such simple oracles without needing permission.

Notably, Sui natively supports authentication via multi-signatures, and this facility could be used to significantly strengthen a simple oracle. If the address that is authorized to update the simple oracle is a multi-sig, then multiple authorities would have to sign each update transaction, allowing for some fault tolerance in case some become unavailable or byzantine. While this is promising, we explore an on-chain variant of this mechanism we call meta oracles next.

The meta oracle – flexibly increasing assurance

There is strength in numbers. For example, it would be reckless for an organization requiring important financial data to rely on a smart contract that only pulls data from a single simple oracle. A corrupt authority could provide incorrect data (although this is auditable on-chain), or an authority could stop operating, leaving a smart contract without critical data. But relying on multiple independent and reputable sources does improve things.

To mitigate these concerns, a meta oracle uses readings from multiple simple oracles to strengthen both safety and availability. In a nutshell, a meta oracle defines a set of authorities – via their simple oracles – that are involved in deriving each reading. When queried, a meta oracle takes at least a threshold of values within a recent time window from the set of authorities and then returns their median value as the value of the oracle.

The parameters of the number of authorities queried and the threshold that need to be fresh are flexible, and can be determined by the developers of the contracts relying on the oracles. However, applying the usual model from distributed systems security: if a meta oracle queries 3f+1 authorities, and has a threshold of 2f+1 (ie 2/3 of them), it can tolerate up to f byzantine authorities that either give incorrect data or no fresh data. The value returned is guaranteed to be within two correct authority values – severely limiting the ability of attackers to influence the oracle values.

The total number of simple oracles included in a meta oracle, as well as the set of acceptable authorities, are flexible, allowing smart contract developers to tune them to their needs in terms of costs on-chain, as well as which set of ecosystem participants they trust. More complex meta oracles are possible – which would allow for governance mechanisms to determine the set of oracles to aggregate, as well as systems of complex collateral and audits to provide incentives for honest data publishing. These more complex meta oracles are beyond the scope of our work outlined in this blog, but we hope the Sui community will experiment with them and showcase what is possible. Anyone can write their favorite variant of the meta-oracle contract using simple oracles thanks to the unrestricted composition properties of the Move programming language.

In terms of cost, reading 10 data sources and getting the median value only takes 7009880 Mist or 0.00700988 SUI.

The meta oracle design illustrates that in a high-throughput, low gas price chain, such as Sui, it is preferable to perform micro-operations on-chain, such as each authority separately publishing values as a simple oracle, and then allow smart contracts to aggregate them according to their needs. Conversely, designs inherited from chains with low throughput and high gas costs per transaction try to do as much as possible off chain, increasing the complexity of their operations and smart contracts. They also incur higher costs on Sui by foregoing native facilities for authentication, authorization, and aggregation, such as multi-sig, which is very cheap.

Uses and limitations

Mysten Labs is currently posting values for crypto prices in this package. We also provide the utilities needed to read these values both on-chain and off-chain here. For example, a contract may use the simple oracle on-chain using this fragment:

public fun get_median_from_oracles_and_transfer(
   oracle1: &SimpleOracle,
   oracle2: &SimpleOracle,
   oracle3: &SimpleOracle,
   mist_amount: u64,
   ctx: &mut TxContext
) {
   let meta_oracle = meta_oracle::new<DecimalValue>(3, 60000, string::utf8(b"SUIUSD"));
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle1);
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle2);
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle3);
   let trusted_data = meta_oracle::median(meta_oracle);
   let value = meta_oracle::value(&trusted_data);
   let decimals = decimal_value::decimal(value);
   let value = decimal_value::value(value);
   let amount = mist_amount * value;
   let usd = MockUSD {
      id

And read the latest value of SUI/USDC and other pairs using the tool on the CLI:

sui client dynamic-field 0xaa14ecfe646b35f118332203df2013bd5c1edd7ef8547d2c85f64b2e15d58279

Since this is a Mysten Labs only oracle, and is offered as-is without any SLA, we strongly discourage anyone from using these oracles for any critical financial operation. Mysten Labs makes no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability, or availability of the information provided by the oracle. The information provided through this oracle does not constitute professional, investment or legal advice. However, they may be acceptable for no-stakes games or as part of meta oracles. Ultimately, developers should use their judgment for their assurance needs.

The Move code of the oracle, as well as tools that anyone can use to to run oracles and use meta oracles, can be found here, and we encourage others to both review it as well as operate oracles for different data.

One important limitation of the simple and meta oracles model as presented (and currently implemented) is that it lacks a business model: oracle operators incur costs, but right now they have no direct way to recover their costs on-chain. Future iterations of this project can explore different models for on-chain payments for reads, as well as different models for potentially having sustainable oracles supported off chain. As alluded above, in an attempt to keep the code easier to understand, all authorization is currently done by transaction creator address, but should instead be authorized by using capabilities to allow for better composition with contracts that implement complex authorization policies.

Oracles and their uses

Oracles in blockchains are fundamental utilities that enable smart contracts to connect to systems outside of the chain and execute based on real world data.

There are many types of contracts that could require oracles. For example, insurance contracts on future weather events may be used by farmers and holiday goers to hedge risk, but require access to real-time weather data to settle; a fantasy trading game could allow players to build a virtual portfolio of shares, and see their portfolio’s value grow (or get rekd) but requires real time access to share prices; prediction markets, that can crowdsource an estimate of the likelihood of geo-political events might require access to outcomes to be decided; a DeFi contracts could require accurate access to cryptocurrency relative prices in order to function properly.

These examples illustrate both the diversity of types of data that oracles may provide, as well as a wide variability in the assurance required to make oracle data useful – from lower for games to very high for contracts with high financial implications. This variability also affects the users’ willingness to pay for higher quality data, which may be low for data used in inconsequential low stakes games, and high for data used in contracts relating to DeFi.

A number of high-assurance oracles are now live on Sui – and we recommend using these for high assurance applications. However, the Mysten Labs team built a “simple oracle” that allows lower assurance values to be posted and read by contracts at a much cheaper gas cost point. We also illustrate a flexible way to combine oracle values from different sources using a “meta oracle” to achieve higher assurance, determined by the developer of the smart contract using the oracle. These oracles showcase the advantages of using native features of Sui to keep costs and complexity down and performance up: from native authentication, tables, and PTBs to read-only shared objects.

The simple oracle – a weak primitive

A simple oracle publishes a data stream. Each data item has some standard metadata such as a ticker symbol, a sequence number, a timestamp, and a reading identifier, as well as the actual value of the data item. The oracle is represented on-chain as a shared object that contains a table with data values, including the latest value and historical values that were archived.

Updating the oracle or archiving values are operations gated to only be authorized by a single authority that publishes the oracles. Currently, this access control relies on checking the update transaction address, but in the future we could extend this to use capabilities to increase flexibility. Multiple updates to multiple oracles from the same authority may be bundled together into a single Programmable Transaction Block (PTB). This results in a very economical operation: as an illustration we can update 30 values every 5 seconds only using 1843600 units of gas (MIST) or 0.0018436 SUI per on-chain transaction.

In order to read historical values provided by an oracle, a contract must take the shared object by reference and only read it. This use of a shared object in read-only mode is extremely efficient, as it does not induce contention, and all transaction reading values are executed in parallel in the Sui execution engine. The operation of reading a simple oracle value is extremely gas efficient as it only reads a dynamic field.

Anyone can run a simple oracle. In the spirit of permissionlessness and decentralization, organizations could coordinate off chain to determine a set of ticker symbols and conventions and independently begin emitting values for these data types. Other oracle operators could start operating such simple oracles without needing permission.

Notably, Sui natively supports authentication via multi-signatures, and this facility could be used to significantly strengthen a simple oracle. If the address that is authorized to update the simple oracle is a multi-sig, then multiple authorities would have to sign each update transaction, allowing for some fault tolerance in case some become unavailable or byzantine. While this is promising, we explore an on-chain variant of this mechanism we call meta oracles next.

The meta oracle – flexibly increasing assurance

There is strength in numbers. For example, it would be reckless for an organization requiring important financial data to rely on a smart contract that only pulls data from a single simple oracle. A corrupt authority could provide incorrect data (although this is auditable on-chain), or an authority could stop operating, leaving a smart contract without critical data. But relying on multiple independent and reputable sources does improve things.

To mitigate these concerns, a meta oracle uses readings from multiple simple oracles to strengthen both safety and availability. In a nutshell, a meta oracle defines a set of authorities – via their simple oracles – that are involved in deriving each reading. When queried, a meta oracle takes at least a threshold of values within a recent time window from the set of authorities and then returns their median value as the value of the oracle.

The parameters of the number of authorities queried and the threshold that need to be fresh are flexible, and can be determined by the developers of the contracts relying on the oracles. However, applying the usual model from distributed systems security: if a meta oracle queries 3f+1 authorities, and has a threshold of 2f+1 (ie 2/3 of them), it can tolerate up to f byzantine authorities that either give incorrect data or no fresh data. The value returned is guaranteed to be within two correct authority values – severely limiting the ability of attackers to influence the oracle values.

The total number of simple oracles included in a meta oracle, as well as the set of acceptable authorities, are flexible, allowing smart contract developers to tune them to their needs in terms of costs on-chain, as well as which set of ecosystem participants they trust. More complex meta oracles are possible – which would allow for governance mechanisms to determine the set of oracles to aggregate, as well as systems of complex collateral and audits to provide incentives for honest data publishing. These more complex meta oracles are beyond the scope of our work outlined in this blog, but we hope the Sui community will experiment with them and showcase what is possible. Anyone can write their favorite variant of the meta-oracle contract using simple oracles thanks to the unrestricted composition properties of the Move programming language.

In terms of cost, reading 10 data sources and getting the median value only takes 7009880 Mist or 0.00700988 SUI.

The meta oracle design illustrates that in a high-throughput, low gas price chain, such as Sui, it is preferable to perform micro-operations on-chain, such as each authority separately publishing values as a simple oracle, and then allow smart contracts to aggregate them according to their needs. Conversely, designs inherited from chains with low throughput and high gas costs per transaction try to do as much as possible off chain, increasing the complexity of their operations and smart contracts. They also incur higher costs on Sui by foregoing native facilities for authentication, authorization, and aggregation, such as multi-sig, which is very cheap.

Uses and limitations

Mysten Labs is currently posting values for crypto prices in this package. We also provide the utilities needed to read these values both on-chain and off-chain here. For example, a contract may use the simple oracle on-chain using this fragment:

public fun get_median_from_oracles_and_transfer(
   oracle1: &SimpleOracle,
   oracle2: &SimpleOracle,
   oracle3: &SimpleOracle,
   mist_amount: u64,
   ctx: &mut TxContext
) {
   let meta_oracle = meta_oracle::new<DecimalValue>(3, 60000, string::utf8(b"SUIUSD"));
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle1);
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle2);
   meta_oracle::add_simple_oracle(&mut meta_oracle, oracle3);
   let trusted_data = meta_oracle::median(meta_oracle);
   let value = meta_oracle::value(&trusted_data);
   let decimals = decimal_value::decimal(value);
   let value = decimal_value::value(value);
   let amount = mist_amount * value;
   let usd = MockUSD {
      id

And read the latest value of SUI/USDC and other pairs using the tool on the CLI:

sui client dynamic-field 0xaa14ecfe646b35f118332203df2013bd5c1edd7ef8547d2c85f64b2e15d58279

Since this is a Mysten Labs only oracle, and is offered as-is without any SLA, we strongly discourage anyone from using these oracles for any critical financial operation. Mysten Labs makes no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability, or availability of the information provided by the oracle. The information provided through this oracle does not constitute professional, investment or legal advice. However, they may be acceptable for no-stakes games or as part of meta oracles. Ultimately, developers should use their judgment for their assurance needs.

The Move code of the oracle, as well as tools that anyone can use to to run oracles and use meta oracles, can be found here, and we encourage others to both review it as well as operate oracles for different data.

One important limitation of the simple and meta oracles model as presented (and currently implemented) is that it lacks a business model: oracle operators incur costs, but right now they have no direct way to recover their costs on-chain. Future iterations of this project can explore different models for on-chain payments for reads, as well as different models for potentially having sustainable oracles supported off chain. As alluded above, in an attempt to keep the code easier to understand, all authorization is currently done by transaction creator address, but should instead be authorized by using capabilities to allow for better composition with contracts that implement complex authorization policies.

Read Next