Skip to content

Commit

Permalink
feat: cache prices in optimistic oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
doomsower committed Apr 16, 2024
1 parent e5448a2 commit d4c2607
Showing 1 changed file with 39 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/services/OracleServiceV3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
IPriceOracleV3__factory,
RedstonePriceFeed__factory,
safeMulticall,
WAD,
} from "@gearbox-protocol/sdk";
import type {
SetPriceFeedEvent,
Expand All @@ -21,6 +22,7 @@ import type { BigNumber } from "ethers";
import { providers, utils } from "ethers";
import { Inject, Service } from "typedi";

import { CONFIG, ConfigSchema } from "../config";
import { Logger, LoggerInterface } from "../log";
import { AddressProviderService } from "./AddressProviderService";

Expand Down Expand Up @@ -65,10 +67,15 @@ export default class OracleServiceV3 {
@Inject()
providerr: providers.Provider;

@Inject(CONFIG)
config: ConfigSchema;

#oracle?: IPriceOracleV3;
#lastBlock = 0;

#feeds: Record<string, OracleEntry> = {};
// underlying (=tokenTo) -> token -> token price in underlying
#priceCache: Record<string, Record<string, bigint>> = {};

public async launch(block: number): Promise<void> {
this.#lastBlock = ORACLE_START_BLOCK[this.addressProvider.network];
Expand Down Expand Up @@ -97,8 +104,11 @@ export default class OracleServiceV3 {
const result: Record<string, bigint> = {};

for (const [tokenFrom, amount] of Object.entries(tokensFrom)) {
const fromCache = this.#convertCached(tokenFrom, tokenTo, amount);
if (tokenFrom.toLowerCase() === tokenTo.toLowerCase()) {
result[tokenTo.toLowerCase()] = amount;
} else if (this.config.optimistic && !!fromCache) {
result[tokenFrom.toLowerCase()] = fromCache;
} else {
calls.push({
address: this.oracle.address,
Expand All @@ -113,9 +123,13 @@ export default class OracleServiceV3 {

for (let i = 0; i < resp.length; i++) {
const { value, error } = resp[i];
const amountFrom = calls[i].params[0] as bigint;
const tokenFrom = calls[i].params[1] as string;
if (!error && !!value) {
result[tokenFrom.toLowerCase()] = value.toBigInt();
if (this.config.optimistic) {
this.#saveCached(tokenFrom, tokenTo, amountFrom, value.toBigInt());
}
}
}

Expand Down Expand Up @@ -271,6 +285,31 @@ export default class OracleServiceV3 {
}
}

#convertCached(
tokenFrom: string,
tokenTo: string,
amountFrom: bigint,
): bigint | undefined {
const price =
this.#priceCache[tokenTo.toLowerCase()]?.[tokenFrom.toLowerCase()];
if (!price) {
return undefined;
}
return (amountFrom * price) / WAD;
}

#saveCached(
tokenFrom: string,
tokenTo: string,
amountFrom: bigint,
amountTo: bigint,
): void {
const price = (WAD * amountTo) / amountFrom;
const froms = this.#priceCache[tokenTo.toLowerCase()] ?? {};
froms[tokenFrom.toLowerCase()] = price;
this.#priceCache[tokenTo.toLowerCase()] = froms;
}

private get oracle(): IPriceOracleV3 {
if (!this.#oracle) {
throw new Error(`oracle serive is not launched`);
Expand Down

0 comments on commit d4c2607

Please sign in to comment.