EIP1154 - Oracle Interface

# Simple Summary

A standard interface for oracles.

# Abstract

In order for ethereum smart contracts to interact with off-chain systems, oracles must be used. These oracles report values which are normally off-chain, allowing smart contracts to react to the state of off-chain systems. A distinction and a choice is made between push and pull based oracle systems. Furthermore, a standard interface for oracles is described here, allowing different oracle implementations to be interchangeable.

# Motivation

The Ethereum ecosystem currently has many different oracle implementations available, but they do not provide a unified interface. Smart contract systems would be locked into a single set of oracle implementations, or they would require developers to write adapters/ports specific to the oracle system chosen in a given project.

Beyond naming differences, there is also the issue of whether or not an oracle report-resolving transaction pushes state changes by calling affected contracts, or changes the oracle state allowing dependent contracts to pull the updated value from the oracle. These differing system semantics could introduce inefficiencies when adapting between them.

Ultimately, the value in different oracle systems comes from their underlying resolution mechanics, and points where these systems are virtually identical should be standardized.

These oracles may be used for answering questions about "real-world events", where each ID can be correlated with a specification of a question and its answers (so most likely for prediction markets, basically).

Another use case could be for decision-making processes, where the results given by the oracle represent decisions made by the oracle (e.g. futarchies). DAOs may require their use in decision making processes.

Both the ID and the results are intentionally unstructured so that things like time series data (via splitting the ID) and different sorts of results (like one of a few, any subset of up to 256, or some value in a range with up to 256 bits of granularity) can be represented.

# Specification

Oracle
An entity which reports data to the blockchain.
Oracle consumer
A smart contract which receives data from an oracle.
ID
A way of indexing the data which an oracle reports. May be derived from or tied to a question for which the data provides the answer.
Result
Data associated with an id which is reported by an oracle. This data oftentimes will be the answer to a question tied to the id. Other equivalent terms that have been used include: answer, data, outcome.
Report
A pair (ID, result) which an oracle sends to an oracle consumer.
interface OracleConsumer {
    function receiveResult(bytes32 id, bytes result) external;
}
1
2
3

receiveResult MUST revert if the msg.sender is not an oracle authorized to provide the result for that id.

receiveResult MUST revert if receiveResult has been called with the same id before.

receiveResult MAY revert if the id or result cannot be handled by the consumer.

Consumers MUST coordinate with oracles to determine how to encode/decode results to and from bytes. For example, abi.encode and abi.decode may be used to implement a codec for results in Solidity. receiveResult SHOULD revert if the consumer receives a unexpected result format from the oracle.

The oracle can be any Ethereum account.

# Rationale

The specs are currently very similar to what is implemented by ChainLink (which can use any arbitrarily-named callback) and Oraclize (which uses __callback).

With this spec, the oracle pushes state to the consumer, which must react accordingly to the updated state. An alternate pull-based interface can be prescribed, as follows:

# Alternate Pull-based Interface

Here are alternate specs loosely based on Gnosis prediction market contracts v1. Reality Check also exposes a similar endpoint (getFinalAnswer).

interface Oracle {
    function resultFor(bytes32 id) external view returns (bytes result);
}
1
2
3

resultFor MUST revert if the result for an id is not available yet.

resultFor MUST return the same result for an id after that result is available.

# Push vs Pull

Note that push-based interfaces may be adapted into pull-based interfaces. Simply deploy an oracle consumer which stores the result received and implements resultFor accordingly.

Similarly, every pull-based system can be adapted into a push-based system: just add a method on the oracle smart contract which takes an oracle consumer address and calls receiveResult on that address.

In both cases, an additional transaction would have to be performed, so the choice to go with push or pull should be based on the dominant use case for these oracles.

In the simple case where a single account has the authority to decide the outcome of an oracle question, there is no need to deploy an oracle contract and store the outcome on that oracle contract. Similarly, in the case where the outcome comes down to a vote, existing multisignature wallets can be used as the authorized oracle.

# Multiple Oracle Consumers

In the case that many oracle consumers depend on a single oracle result and all these consumers expect the result to be pushed to them, the push and pull adaptations mentioned before may be combined if the pushing oracle cannot be trusted to send the same result to every consumer (in a sense, this forwards the trust to the oracle adaptor implementation).

In a pull-based system, each of the consumers would have to be called to pull the result from the oracle contract, but in the proposed push-based system, the adapted oracle would have to be called to push the results to each of the consumers.

Transaction-wise, both systems are roughly equivalent in efficiency in this scenario, but in the push-based system, there's a need for the oracle consumers to store the results again, whereas in the pull-based system, the consumers may continue to refer to the oracle for the results. Although this may be somewhat less efficient, requiring the consumers to store the results can also provide security guarantees, especially with regards to result immutability.

# Result Immutability

In both the proposed specification and the alternate specification, results are immutable once they are determined. This is due to the expectation that typical consumers will require results to be immutable in order to determine a resulting state consistently. With the proposed push-based system, the consumer enforces the result immutability requirement, whereas in the alternate pull-based system, either the oracle would have to be trusted to implement the spec correctly and enforce the immutability requirement, or the consumer would also have to handle result immutability.

For data which mutates over time, the id field may be structured to specify "what" and "when" for the data (using 128 bits to specify "when" is still safe for many millennia).

# Implementation

Copyright and related rights waived via CC0 (opens new window).

▲ Powered by Vercel