HydraDX-node icon indicating copy to clipboard operation
HydraDX-node copied to clipboard

EMA oracle events

Open mrq1911 opened this issue 3 months ago • 1 comments

emit event when oracle price changes on end of the block

mrq1911 avatar Oct 11 '25 08:10 mrq1911

Overview

We'll emit event in on_finalize for when price of an oracle is updated, event will include information for the Periods for which it was updated and the updated price for that period.

Event type

We'll introduce one event to emit updates for each (source,assets) pair

		/// Oracle price was updated by several entries
		OracleUpdated {
			source: Source,
			assets: (AssetId, AssetId),
			update: Vec<(OraclePeriod, OracleEntry<BlockNumberFor<T>>)>,
		},

Implementation Spec

fn update_oracle

Change signature of update_oracle. We are interested in the updated price only, so we return only that.

	/// Update the oracle of the given source, assets and period with `oracle_entry`.
	/// returns the updated price of the oracle
	fn update_oracle(
		src: Source,
		assets: (AssetId, AssetId),
		period: OraclePeriod,
		incoming_entry: OracleEntry<BlockNumberFor<T>>,
	) -> OracleEntry<BlockNumberFor<T>>

fn update_oracles_from_accumulator

Introduce a vector of type Vec<(OraclePeriod, Price)>, catch returned Price from update_oracle, push tuple of (OraclePeriod, Price) to this vec for event construction.

			// accumulate updates to oracle for event emission
			let mut updates = vec![];
			// First we update the non-immediate oracles with the value of the `LastBlock` oracle.
			for period in T::SupportedPeriods::get()
				.into_iter()
				.filter(|p| *p != OraclePeriod::LastBlock)
			{
				updates.push((
					period,
					Self::update_oracle(src.clone(), assets.clone(), period, oracle_entry.clone()),
				));
			}
			// As we use (the old value of) the `LastBlock` entry to update the other oracles it
			// gets updated last.
			updates.push((
				OraclePeriod::LastBlock,
				Self::update_oracle(src, assets, OraclePeriod::LastBlock, oracle_entry.clone()),
			));

			Self::deposit_event(Event::<T>::OracleUpdated {
				source: src,
				assets,
				updates,
			});

Design Considerations

  • update_oracle returns updated OracleEntry only not the blocknumber from when its updated
  • Could considering emitting only a portion of OracleEntry instead of the whole type
  • OracleUpdated.updates is a vec of tuples, which is not very descriptive, maybe something like a dictionary type would be more useful, not sure if one is available though

talhadaar avatar Dec 11 '25 08:12 talhadaar