Skip to content

Commit

Permalink
add the oracle get earliest observation method (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
moodysalem authored Sep 23, 2024
1 parent 75a2dc8 commit 993bc0e
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
scarb 2.8.1
scarb 2.8.2
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ block_id.number = "677957"

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.30.0" }
assert_macros = "2.8.0"
assert_macros = "2.8.2"
41 changes: 41 additions & 0 deletions src/oracle.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ use starknet::{ContractAddress};

#[starknet::interface]
pub trait IOracle<TContractState> {
// Returns the timestamp of the earliest observation for a given pair, or Option::None if the
// pair has no observations
fn get_earliest_observation_time(
self: @TContractState, token_a: ContractAddress, token_b: ContractAddress
) -> Option<u64>;

// Returns the time weighted average tick between the given start and end time
fn get_average_tick_over_period(
self: @TContractState,
Expand Down Expand Up @@ -102,6 +108,7 @@ pub trait IOracle<TContractState> {

#[starknet::contract]
pub mod Oracle {
use core::cmp::{max};
use core::num::traits::{Zero, Sqrt, WideMul};
use core::traits::{Into};
use ekubo::components::owned::{Owned as owned_component};
Expand Down Expand Up @@ -291,6 +298,40 @@ pub mod Oracle {

#[abi(embed_v0)]
impl OracleImpl of IOracle<ContractState> {
fn get_earliest_observation_time(
self: @ContractState, token_a: ContractAddress, token_b: ContractAddress
) -> Option<u64> {
let oracle_token = self.oracle_token.read();

if token_a == oracle_token || token_b == oracle_token {
let (token0, token1) = if token_a < token_b {
(token_a, token_b)
} else {
(token_b, token_a)
};
let entry = self.pool_state.entry((token0, token1));
let count = entry.count.read();
if count.is_zero() {
Option::None
} else {
let first = entry.snapshots.entry(0).read();
Option::Some(first.block_timestamp)
}
} else {
if let Option::Some(time_a) = self
.get_earliest_observation_time(oracle_token, token_a) {
if let Option::Some(time_b) = self
.get_earliest_observation_time(oracle_token, token_b) {
Option::Some(max(time_a, time_b))
} else {
Option::None
}
} else {
Option::None
}
}
}

fn get_average_tick_over_period(
self: @ContractState,
base_token: ContractAddress,
Expand Down
29 changes: 29 additions & 0 deletions src/oracle_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,35 @@ fn test_get_tick_cumulative_at_future() {
oracle.get_average_tick_over_period(pool_key.token0, pool_key.token1, start, start + 1);
}

#[test]
#[fork("mainnet")]
fn test_get_earliest_observation_time() {
let (pool_key_0, pool_key_1) = setup();
let oracle = IOracleDispatcher { contract_address: pool_key_0.extension };

let start = get_block_timestamp() + 10;
cheat_block_timestamp(oracle.contract_address, start, CheatSpan::Indefinite);
ekubo_core().initialize_pool(pool_key_0, Zero::zero());
cheat_block_timestamp(oracle.contract_address, start + 15, CheatSpan::Indefinite);
ekubo_core().initialize_pool(pool_key_1, Zero::zero());

assert_eq!(
oracle.get_earliest_observation_time(pool_key_0.token0, pool_key_0.token1).unwrap(), start
);
assert_eq!(
oracle.get_earliest_observation_time(pool_key_1.token0, pool_key_1.token1).unwrap(),
start + 15
);
assert_eq!(
oracle.get_earliest_observation_time(pool_key_0.token0, pool_key_0.token1).unwrap(), start
);
// token0, token2
assert_eq!(
oracle.get_earliest_observation_time(pool_key_0.token0, pool_key_1.token1).unwrap(),
start + 15
);
}

// assumes there is 0 liquidity so swaps are free
fn move_price_to_tick(pool_key: PoolKey, tick: i129) {
let tick_current = ekubo_core().get_pool_price(pool_key).tick;
Expand Down

0 comments on commit 993bc0e

Please sign in to comment.