Obtains the on-chain data and it's ready to report it
The Oracle is an
abstractcontract which needs to be inherited and completely implemented. The basic functionality is all there, each Oracle implementation needs to handle their own way of gathering and validating the data. The
abstractOracle handles time delays, making the data available, as well as emitting the relevant events.
An Oracle has a simple initialization process because most of the complexity will be contained in the Oracle implementations that inherit the
An oracle needs these parameters on deployment:
timeUpdateWindow- This interval is defined as the minimum number of seconds between subsequent updates. The oracle has to wait at least
All parameters are
immutable(they can't change) after the contract was deployed.
An external trusted actor needs to call
updateto make the Oracle retrieve the data it needs. The update method is also protected against re-entrancy. First, the Oracle checks if enough time has passed since the previous execution (using
timeUpdateWindow), then it proceeds to obtain the on-chain value.
To reduce the problems that might arise from doing external calls to external systems, an external call is simulated towards an
abstractmethod that the Oracle implementation contains. This is done by using a Solidity feature known as
try/catchbut it can also be achieved by doing low-level calls to its own implementation. Having this approach protects the call to
getValuefrom unsafe execution, as well as failed calls since it handles all cases in the
Considering all goes well, a new value is obtained and it is saved as the next available value. This next available value becomes active after the next successful call to
update. A successful execution swaps the next available value as the currently reported value and sets the next available value as the retrieved value. This means the Oracle has a minimum delay set as
timeUpdateWindowafter receiving a new value from the outside source.
Having this delay allows approved actors to veto the value, in case the oracle or the data source went wrong.
Once at least one successful update was performed, the value can be retrieved. This is usually queried by the Relayer and pushed into Collybus.
Also, when querying the value, a boolean flag is also returned which signifies if the latest
updateexecuted successfully. This flag should always be checked for truthness when retrieving the value.
As described in the update section, a value can be vetoed by approved actors. This feature is important just in case the value that is about to be reported by the Oracle is invalid. This could happen because of a compromised data source but also protects from flashloan attacks.
The approved actors have the possibility to
unpausethe Oracle if they want to veto the value.
A pause stops the Oracle from returning a value.
Resetting can be done only when the Oracle is paused, and completely resets the Oracle's state. Once the Oracle's state was cleared, a new update happens immediatelly, meaning the obtained value becomes active right away (without the need to wait the usual
Once a reset was performed, the Oracle can be unpaused. Having the Oracle is unpaused, it can report the recorded value.
These methods can be called by anyone.
This is the abstract method that needs to be implemented by each Oracle instance. It will contain the specific logic of getting values and transforming them in a way that makes them usable by Collybus.
Returns the value and if the last retrieval was successful. One must check if the last retrieval was successful to know if the returned value is valid.
The last Unix timestamp at which the Oracle was updated.
The minimum time in seconds between sequential Oracle updates.
The value that will become the reported one (by
value) after a new successful
Updates the Oracle values if at least
timeUpdateWindowhas passed since the last update.
Disables calls to
value. This method is used discretionarily when the Oracle or an adjacent system misbehaves.
Enables calls to
value. This method is used after the Oracle was reset, in case the Oracle or an adjacent system mibehaved.
Resets the Oracle value if the Oracle or an adjacent system misbehaved. Can only be called when the Oracle is paused.