Skip to content

Commit

Permalink
feat: implement oracle_utils (#570)
Browse files Browse the repository at this point in the history
* feat: implement oracle_utils

* fmt

* tests: fix tests

* fmt

* simplify boolean condition
  • Loading branch information
zarboq authored Nov 2, 2023
1 parent 08409a1 commit 12aca79
Show file tree
Hide file tree
Showing 45 changed files with 447 additions and 162 deletions.
6 changes: 3 additions & 3 deletions src/adl/adl_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use satoru::market::market_utils::{
};
use satoru::adl::error::AdlError;
use satoru::data::keys;
use satoru::utils::arrays::u64_are_gte;
use satoru::utils::arrays::are_gte_u64;
use satoru::position::position_utils;
use satoru::position::position::Position;
use satoru::order::order::{Order, OrderType, DecreasePositionSwapType};
Expand Down Expand Up @@ -91,7 +91,7 @@ fn update_adl_state(
) {
let latest_adl_block = get_latest_adl_block(data_store, market, is_long);
assert(
u64_are_gte(max_oracle_block_numbers, latest_adl_block),
are_gte_u64(max_oracle_block_numbers, latest_adl_block),
AdlError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED
);
let _market = get_enabled_market(data_store, market);
Expand Down Expand Up @@ -204,7 +204,7 @@ fn validate_adl(
assert(is_adl_enabled, AdlError::ADL_NOT_ENABLED);
let latest_block = get_latest_adl_block(data_store, market, is_long);
assert(
u64_are_gte(max_oracle_block_numbers, latest_block),
are_gte_u64(max_oracle_block_numbers, latest_block),
AdlError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED
);
}
Expand Down
2 changes: 0 additions & 2 deletions src/bank/bank.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ mod Bank {
get_caller_address, get_contract_address, ContractAddress, contract_address_const
};

use debug::PrintTrait;

// Local imports.
use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait};
use super::IBank;
Expand Down
1 change: 0 additions & 1 deletion src/bank/strict_bank.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ mod StrictBank {
use starknet::{
get_caller_address, get_contract_address, ContractAddress, contract_address_const
};
use debug::PrintTrait;

// Local imports.
use satoru::bank::bank::{Bank, IBank};
Expand Down
1 change: 0 additions & 1 deletion src/config/config.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ mod Config {
use starknet::{get_caller_address, ContractAddress, contract_address_const,};
use poseidon::poseidon_hash_span;

use debug::PrintTrait;

// Local imports.
use satoru::role::role;
Expand Down
1 change: 0 additions & 1 deletion src/config/timelock.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ mod Timelock {
use core::zeroable::Zeroable;
use starknet::{get_caller_address, ContractAddress, contract_address_const};

use debug::PrintTrait;

// Local imports.

Expand Down
1 change: 0 additions & 1 deletion src/data/data_store.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,6 @@ mod DataStore {
use nullable::NullableTrait;
use zeroable::Zeroable;
use alexandria_storage::list::{ListTrait, List};
use debug::PrintTrait;
use poseidon::poseidon_hash_span;

// Local imports.
Expand Down
1 change: 0 additions & 1 deletion src/deposit/deposit_vault.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ mod DepositVault {
use core::zeroable::Zeroable;
use starknet::{get_caller_address, ContractAddress, contract_address_const};

use debug::PrintTrait;

// Local imports.
use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait};
Expand Down
1 change: 0 additions & 1 deletion src/deposit/execute_deposit_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use starknet::ContractAddress;
use result::ResultTrait;

use debug::PrintTrait;
// Local imports.
use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait};
use satoru::callback::callback_utils::after_deposit_execution;
Expand Down
1 change: 0 additions & 1 deletion src/exchange/base_order_handler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ mod BaseOrderHandler {
use core::traits::Into;
use starknet::{get_caller_address, ContractAddress, contract_address_const};

use debug::PrintTrait;
use result::ResultTrait;

// Local imports.
Expand Down
1 change: 0 additions & 1 deletion src/exchange/liquidation_handler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ mod LiquidationHandler {
use satoru::exchange::base_order_handler::{IBaseOrderHandler, BaseOrderHandler};
use satoru::liquidation::liquidation_utils::create_liquidation_order;
use satoru::exchange::order_handler;
use debug::PrintTrait;
use satoru::feature::feature_utils::validate_feature;
use satoru::exchange::order_handler::{IOrderHandler, OrderHandler};
use satoru::utils::starknet_utils;
Expand Down
1 change: 0 additions & 1 deletion src/fee/fee_handler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ mod FeeHandler {
use core::zeroable::Zeroable;
use starknet::{get_caller_address, ContractAddress, contract_address_const};

use debug::PrintTrait;

// Local imports.
use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait};
Expand Down
3 changes: 3 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ mod oracle {
mod oracle_utils;
mod oracle;
mod price_feed;
mod interfaces {
mod account;
}
}

// `order` contains order management functions.
Expand Down
1 change: 0 additions & 1 deletion src/market/market_factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ mod MarketFactory {
use starknet::syscalls::deploy_syscall;
use poseidon::poseidon_hash_span;

use debug::PrintTrait;

// Local imports.
use satoru::role::role;
Expand Down
57 changes: 50 additions & 7 deletions src/oracle/error.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,10 @@ mod OracleError {
panic(array!['block number not sorted', data_1.into(), data_2.into()])
}

fn ARRAY_OUT_OF_BOUNDS_FELT252(mut data_1: Span<felt252>, data_2: u128, msg: felt252) {
fn ARRAY_OUT_OF_BOUNDS_FELT252(mut data_1: Span<Span<felt252>>, data_2: usize, msg: felt252) {
let mut data: Array<felt252> = array!['array out of bounds felt252'];
let mut length = data_1.len();
loop {
if length == 0 {
break;
}
data.append(*data_1.pop_front().expect('array pop_front failed'));
};
// TODO add data_1 data to error
data.append(data_2.into());
data.append(msg);
panic(data)
Expand Down Expand Up @@ -150,4 +145,52 @@ mod OracleError {
data.append(block_number.into());
panic(data)
}

fn BLOCK_NUMBER_NOT_WITHIN_RANGE(mut data_1: Span<u64>, mut data_2: Span<u64>, data_3: u64) {
let mut data: Array<felt252> = array!['block number not within range'];
let mut length = data_1.len();
loop {
if length == 0 {
break;
}
let el = *data_1.pop_front().unwrap();
data.append(el.into());
};
let mut length_2 = data_2.len();
loop {
if length_2 == 0 {
break;
}
let el = *data_2.pop_front().unwrap();
data.append(el.into());
};
data.append(data_3.into());
panic(data)
}

fn EMPTY_COMPACTED_PRICE(data_1: usize) {
panic(array!['empty compacted price', data_1.into()])
}

fn EMPTY_COMPACTED_TIMESTAMP(data_1: usize) {
panic(array!['empty compacted timestamp', data_1.into()])
}

fn INVALID_SIGNATURE(data_1: felt252, data_2: felt252) {
panic(array!['invalid signature', data_1.into(), data_2.into()])
}

fn BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED(mut data_1: Span<u64>, data_2: u64) {
let mut data: Array<felt252> = array!['block numbers too small'];
let mut length = data_1.len();
loop {
if length == 0 {
break;
}
let el = *data_1.pop_front().unwrap();
data.append(el.into());
};
data.append(data_2.into());
panic(data)
}
}
76 changes: 76 additions & 0 deletions src/oracle/interfaces/account.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#[starknet::interface]
trait IAccount<TContractState> {
fn __validate_declare__(self: @TContractState, class_hash: felt252) -> felt252;
fn __validate_deploy__(
self: @TContractState,
class_hash: felt252,
contract_address_salt: felt252,
owner: felt252,
guardian: felt252
) -> felt252;
// External

/// @notice Changes the owner
/// Must be called by the account and authorised by the owner and a guardian (if guardian is set).
/// @param new_owner New owner address
/// @param signature_r Signature R from the new owner
/// @param signature_S Signature S from the new owner
/// Signature is required to prevent changing to an address which is not in control of the user
/// Signature is the Signed Message of this hash:
/// hash = pedersen(0, (change_owner selector, chainid, contract address, old_owner))
fn change_owner(
ref self: TContractState, new_owner: felt252, signature_r: felt252, signature_s: felt252
);

/// @notice Changes the guardian
/// Must be called by the account and authorised by the owner and a guardian (if guardian is set).
/// @param new_guardian The address of the new guardian, or 0 to disable the guardian
/// @dev can only be set to 0 if there is no guardian backup set
fn change_guardian(ref self: TContractState, new_guardian: felt252);

/// @notice Changes the backup guardian
/// Must be called by the account and authorised by the owner and a guardian (if guardian is set).
/// @param new_guardian_backup The address of the new backup guardian, or 0 to disable the backup guardian
fn change_guardian_backup(ref self: TContractState, new_guardian_backup: felt252);

/// @notice Triggers the escape of the owner when it is lost or compromised.
/// Must be called by the account and authorised by just a guardian.
/// Cannot override an ongoing escape of the guardian.
/// @param new_owner The new account owner if the escape completes
/// @dev This method assumes that there is a guardian, and that `_newOwner` is not 0.
/// This must be guaranteed before calling this method, usually when validating the transaction.
fn trigger_escape_owner(ref self: TContractState, new_owner: felt252);

/// @notice Triggers the escape of the guardian when it is lost or compromised.
/// Must be called by the account and authorised by the owner alone.
/// Can override an ongoing escape of the owner.
/// @param new_guardian The new account guardian if the escape completes
/// @dev This method assumes that there is a guardian, and that `new_guardian` can only be 0
/// if there is no guardian backup.
/// This must be guaranteed before calling this method, usually when validating the transaction
fn trigger_escape_guardian(ref self: TContractState, new_guardian: felt252);

/// @notice Completes the escape and changes the owner after the security period
/// Must be called by the account and authorised by just a guardian
/// @dev This method assumes that there is a guardian, and that the there is an escape for the owner.
/// This must be guaranteed before calling this method, usually when validating the transaction.
fn escape_owner(ref self: TContractState);

/// @notice Completes the escape and changes the guardian after the security period
/// Must be called by the account and authorised by just the owner
/// @dev This method assumes that there is a guardian, and that the there is an escape for the guardian.
/// This must be guaranteed before calling this method. Usually when validating the transaction.
fn escape_guardian(ref self: TContractState);

/// @notice Cancels an ongoing escape if any.
/// Must be called by the account and authorised by the owner and a guardian (if guardian is set).
fn cancel_escape(ref self: TContractState);

// Views
fn get_owner(self: @TContractState) -> felt252;
fn get_guardian(self: @TContractState) -> felt252;
fn get_guardian_backup(self: @TContractState) -> felt252;
fn get_name(self: @TContractState) -> felt252;
fn get_guardian_escape_attempts(self: @TContractState) -> u32;
fn get_owner_escape_attempts(self: @TContractState) -> u32;
}
27 changes: 11 additions & 16 deletions src/oracle/oracle.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,11 @@ struct SetPricesCache {
/// Struct used in validate_prices as an inner cache.
#[derive(Default, Drop)]
struct SetPricesInnerCache {
/// The current price index to retrieve from compactedMinPrices and compactedMaxPrices
/// to construct the minPrices and maxPrices array.
price_index: u128,
/// The current price index to retrieve from compacted_min_prices and compacted_max_prices
/// to construct the min_prices and max_prices array.
price_index: usize,
/// The current signature index to retrieve from the signatures array.
signature_index: u128,
signature_index: usize,
/// The index of the min price in min_prices for the current signer.
min_price_index: u128,
/// The index of the max price in max_prices for the current signer.
Expand Down Expand Up @@ -456,7 +456,7 @@ mod Oracle {
}

let validated_price = *validated_prices.at(len);
if !validated_price.min.is_zero() || !validated_price.max.is_zero() {
if !self.primary_prices.read(validated_price.token).is_zero() {
OracleError::DUPLICATED_TOKEN_PRICE();
}
self
Expand All @@ -472,8 +472,8 @@ mod Oracle {
validated_price.token,
Price { min: validated_price.min, max: validated_price.max }
);
len += 1;
};
len += 1;
}

/// Validate prices in params.
Expand All @@ -486,7 +486,6 @@ mod Oracle {
let signers = self.get_signers_(data_store, @params);

let mut cache: SetPricesCache = Default::default();

cache
.min_block_confirmations = data_store
.get_u128(keys::min_oracle_block_confirmations())
Expand Down Expand Up @@ -534,7 +533,6 @@ mod Oracle {
oracle_utils::get_uncompacted_oracle_timestamp(
params.compacted_oracle_timestamps.span(), i
);

if report_info.min_oracle_block_number > get_block_number() {
OracleError::INVALID_BLOCK_NUMBER(
report_info.min_oracle_block_number, get_block_number()
Expand Down Expand Up @@ -588,7 +586,6 @@ mod Oracle {
break;
}
inner_cache.price_index = (i * signers_len + j).into();

inner_cache
.min_prices
.append(
Expand Down Expand Up @@ -637,12 +634,11 @@ mod Oracle {
compacted_max_span, inner_cache.signature_index
);

if inner_cache.signature_index >= signatures_span.len().into() {
if inner_cache.signature_index >= signatures_span.len() {
OracleError::ARRAY_OUT_OF_BOUNDS_FELT252(
signatures_span, inner_cache.signature_index, 'signatures'
);
}

if inner_cache.min_price_index >= inner_cache.min_prices.len().into() {
OracleError::ARRAY_OUT_OF_BOUNDS_U128(
inner_cache.min_prices.span(), inner_cache.min_price_index, 'min_prices'
Expand Down Expand Up @@ -682,14 +678,10 @@ mod Oracle {
report_info.min_price, report_info.max_price
);
}

oracle_utils::validate_signer(
self.get_salt(),
report_info,
arrays::get_felt252(
signatures_span,
inner_cache.signature_index.try_into().expect('u128 into u32 failed')
),
*signatures_span.at(inner_cache.signature_index),
signers_span.at(j)
);

Expand Down Expand Up @@ -890,6 +882,9 @@ mod Oracle {
self: @ContractState, data_store: IDataStoreDispatcher, token: ContractAddress,
) -> (bool, u128) {
let token_id = data_store.get_token_id(token);
if token_id == 0 {
return (false, 0);
}
let response = self.price_feed.read().get_data_median(DataType::SpotEntry(token_id));

if response.price <= 0 {
Expand Down
Loading

0 comments on commit 12aca79

Please sign in to comment.