Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fossil client callback settles round #186

Merged
merged 5 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions src/fossil_client/contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod FossilClient {
use pitch_lake::library::constants::PROGRAM_ID;
use pitch_lake::vault::interface::{IVaultDispatcher, IVaultDispatcherTrait};
use pitch_lake::option_round::interface::{IOptionRoundDispatcher, IOptionRoundDispatcherTrait};
use pitch_lake::fossil_client::interface::{JobRequest, FossilResult, L1Data, IFossilClient,};
use pitch_lake::fossil_client::interface::{JobRequest, FossilResult, L1Data, IFossilClient, FossilCallbackReturn};

// *************************************************************************
// STORAGE
Expand Down Expand Up @@ -63,7 +63,7 @@ mod FossilClient {
impl FossilClientImpl of IFossilClient<ContractState> {
fn fossil_callback(
ref self: ContractState, mut request: Span<felt252>, mut result: Span<felt252>
) {
) -> FossilCallbackReturn {
// Deserialize request & result
let JobRequest { vault_address, timestamp, program_id } = Serde::deserialize(
ref request
Expand All @@ -89,15 +89,7 @@ mod FossilClient {

// Relay L1 data to the vault
IVaultDispatcher { contract_address: vault_address }
.fossil_client_callback(l1_data, timestamp);

// Emit callback success event
self
.emit(
Event::FossilCallbackSuccess(
FossilCallbackSuccess { vault_address, l1_data, timestamp }
)
);
.fossil_client_callback(l1_data, timestamp)
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion src/fossil_client/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use starknet::{ContractAddress, StorePacking};

#[starknet::interface]
trait IFossilClient<TContractState> {
fn fossil_callback(ref self: TContractState, request: Span<felt252>, result: Span<felt252>);
fn fossil_callback(ref self: TContractState, request: Span<felt252>, result: Span<felt252>) -> FossilCallbackReturn;
}

// *************************************************************************
Expand Down Expand Up @@ -48,6 +48,17 @@ struct FossilResult {
proof: Span<felt252>,
}

#[derive(Copy, Drop, Serde)]
enum FossilCallbackReturn {
RoundSettled: RoundSettledReturn,
FirstRoundInitialized,
}

#[derive(Copy, Drop, Serde)]
struct RoundSettledReturn{
total_payout: u256
}

impl SerdeFossilResult of Serde<FossilResult> {
fn serialize(self: @FossilResult, ref output: Array<felt252>) {
self.l1_data.serialize(ref output);
Expand Down
1 change: 1 addition & 0 deletions src/tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mod utils {
mod accelerators;
mod event_helpers;
mod general_helpers;
mod fossil_client_helpers;
mod setup;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use pitch_lake::tests::{
helpers::{
accelerators::{
accelerate_to_auctioning, accelerate_to_auctioning_custom, accelerate_to_running,
accelerate_to_running_custom, timeskip_and_settle_round, timeskip_and_end_auction,
accelerate_to_running_custom, timeskip_and_end_auction,
//accelerate_to_running_custom_option_round,
},
setup::{setup_facade, setup_test_auctioning_bidders},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use pitch_lake::{
helpers::{
accelerators::{
accelerate_to_auctioning, accelerate_to_running, accelerate_to_running_custom,
accelerate_to_settled, clear_event_logs, timeskip_and_settle_round
accelerate_to_settled, clear_event_logs
},
setup::{FOSSIL_PROCESSOR, setup_facade, deploy_vault, deploy_eth},
event_helpers::{assert_fossil_callback_success_event}, general_helpers::{to_gwei},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use starknet::{
testing::{set_contract_address, set_block_timestamp}
};
use pitch_lake::{
vault::interface::{VaultType}, fossil_client::interface::{L1Data, JobRequest, FossilResult},
vault::interface::{VaultType}, fossil_client::interface::{L1Data, JobRequest, FossilResult, FossilCallbackReturn},
vault::contract::Vault, vault::contract::Vault::Errors as vErrors,
fossil_client::contract::FossilClient::Errors as fErrors, option_round::interface::PricingData,
library::pricing_utils,
Expand All @@ -13,7 +13,7 @@ use pitch_lake::{
helpers::{
accelerators::{
accelerate_to_auctioning, accelerate_to_auctioning_custom,
accelerate_to_running_custom, accelerate_to_running, timeskip_and_settle_round,
accelerate_to_running_custom, accelerate_to_running,
accelerate_to_settled_custom, timeskip_to_settlement_date, accelerate_to_settled
},
setup::{
Expand All @@ -22,6 +22,7 @@ use pitch_lake::{
},
event_helpers::{clear_event_logs, assert_fossil_callback_success_event},
general_helpers::{to_gwei},
fossil_client_helpers::{get_mock_l1_data, get_mock_result, get_mock_result_serialized, get_request, get_request_serialized}
},
facades::{
vault_facade::{VaultFacade, VaultFacadeTrait},
Expand All @@ -35,7 +36,6 @@ use pitch_lake::{
use pitch_lake::library::pricing_utils::{calculate_strike_price};
use core::integer::{I128Neg};


//#[test]
//#[available_gas(50000000)]
//#[ignore]
Expand All @@ -53,30 +53,6 @@ use core::integer::{I128Neg};
// println!("strike3: {}", strike3);
//}

fn get_mock_l1_data() -> L1Data {
L1Data { twap: to_gwei(33) / 100, volatility: 1009, reserve_price: to_gwei(11) / 10 }
}

fn get_mock_result() -> FossilResult {
FossilResult { proof: array![].span(), l1_data: get_mock_l1_data() }
}

fn get_mock_result_serialized() -> Span<felt252> {
let mut result_serialized = array![];
get_mock_result().serialize(ref result_serialized);
result_serialized.span()
}

fn get_request(ref vault: VaultFacade) -> JobRequest {
vault.get_request_to_settle_round()
}

fn get_request_serialized(ref vault: VaultFacade) -> Span<felt252> {
let mut request_serialized = array![];
get_request(ref vault).serialize(ref request_serialized);
request_serialized.span()
}

// Test only the fossil processor can call the fossil callback

// Fossil Client Contract
Expand Down Expand Up @@ -186,32 +162,6 @@ fn test_default_l1_data_fails() {
);
}

// Test callback event
#[test]
#[available_gas(50000000)]
fn test_callback_event() {
let (mut vault, _) = setup_facade();
let mut current_round = vault.get_current_round();
let fossil_client = vault.get_fossil_client_facade();

accelerate_to_auctioning(ref vault);
accelerate_to_running(ref vault);
timeskip_to_settlement_date(ref vault);
clear_event_logs(array![fossil_client.contract_address]);

set_contract_address(FOSSIL_PROCESSOR());
let request = get_request_serialized(ref vault);
let result = get_mock_result_serialized();
fossil_client.fossil_callback(request, result);

assert_fossil_callback_success_event(
vault.get_fossil_client_facade().contract_address,
vault.contract_address(),
get_mock_result().l1_data,
current_round.get_option_settlement_date()
);
}

// Vault Callback for Client

// Test only fossil client can call fossil client callback
Expand Down Expand Up @@ -249,15 +199,12 @@ fn test_callback_sets_pricing_data_for_round() {
accelerate_to_running(ref vault);
timeskip_to_settlement_date(ref vault);

// Fossil API callback
// Fossil API callback - gets calculation data and settles the round
let request = get_request_serialized(ref vault);
let result = get_mock_result_serialized();
set_contract_address(vault.get_fossil_client_address());
fossil_client.fossil_callback(request, result);

// Settle round using callback data
vault.settle_option_round();

// Check pricing data set as expected
let mut current_round = vault.get_current_round();
let L1Data { twap, volatility, reserve_price } = get_mock_l1_data();
Expand Down Expand Up @@ -426,9 +373,6 @@ fn test_callback_works_as_expected() {
let result = get_mock_result_serialized();
fossil_client.fossil_callback(request, result);

// Settle round
vault.settle_option_round();

let mut next_round = vault.get_current_round();
let l1_data = get_mock_l1_data();
let strike = pricing_utils::calculate_strike_price(vault.get_strike_level(), l1_data.twap);
Expand Down
6 changes: 3 additions & 3 deletions src/tests/utils/facades/fossil_client_facade.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::fossil_client::interface::{
IFossilClientDispatcher, IFossilClientSafeDispatcher, IFossilClientDispatcherTrait,
IFossilClientSafeDispatcherTrait
IFossilClientSafeDispatcherTrait, FossilCallbackReturn
};
use crate::tests::utils::helpers::setup::FOSSIL_PROCESSOR;
use starknet::testing::set_contract_address;
Expand All @@ -27,9 +27,9 @@ impl FossilClientFacadeImpl of FossilClientFacadeTrait {
}

/// Entrypoints
fn fossil_callback(self: FossilClientFacade, request: Span<felt252>, result: Span<felt252>) {
fn fossil_callback(self: FossilClientFacade, request: Span<felt252>, result: Span<felt252>) -> FossilCallbackReturn {
set_contract_address(FOSSIL_PROCESSOR());
self.dispatcher().fossil_callback(request, result);
self.dispatcher().fossil_callback(request, result)
}

#[feature("safe_dispatcher")]
Expand Down
40 changes: 20 additions & 20 deletions src/tests/utils/facades/vault_facade.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use starknet::{ContractAddress, testing::{set_contract_address, set_block_timestamp}};
use openzeppelin_token::erc20::interface::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait};
use pitch_lake::{
fossil_client::interface::{JobRequest, L1Data, FossilResult},
fossil_client::interface::{JobRequest, L1Data, FossilResult, FossilCallbackReturn, RoundSettledReturn},
vault::{
interface::{
VaultType, IVaultDispatcher, IVaultDispatcherTrait, IVaultSafeDispatcher,
Expand Down Expand Up @@ -162,8 +162,8 @@ impl VaultFacadeImpl of VaultFacadeTrait {

/// State transition

fn fossil_client_callback(ref self: VaultFacade, l1_data: L1Data, timestamp: u64) {
self.vault_dispatcher.fossil_client_callback(l1_data, timestamp);
fn fossil_client_callback(ref self: VaultFacade, l1_data: L1Data, timestamp: u64) -> FossilCallbackReturn {
self.vault_dispatcher.fossil_client_callback(l1_data, timestamp)
}

#[feature("safe_dispatcher")]
Expand Down Expand Up @@ -205,26 +205,26 @@ impl VaultFacadeImpl of VaultFacadeTrait {
safe_vault.end_auction().expect_err(error);
}

fn settle_option_round(ref self: VaultFacade) -> u256 {
// @dev Using bystander as caller so that gas fees do not throw off balance calculations
set_contract_address(bystander());
// fn settle_option_round(ref self: VaultFacade) -> u256 {
// // @dev Using bystander as caller so that gas fees do not throw off balance calculations
// set_contract_address(bystander());

// Settle the current round
let mut current_round = self.get_current_round();
let total_payout = self.vault_dispatcher.settle_round();
let total_payout = sanity_checks::settle_option_round(ref current_round, total_payout);
// // Settle the current round
// let mut current_round = self.get_current_round();
// let total_payout = self.vault_dispatcher.settle_round();
// let total_payout = sanity_checks::settle_option_round(ref current_round, total_payout);

let current_round_address = self.get_option_round_address(self.get_current_round_id());
eth_supply_and_approve_all_bidders(current_round_address, self.get_eth_address());
total_payout
}
// let current_round_address = self.get_option_round_address(self.get_current_round_id());
// eth_supply_and_approve_all_bidders(current_round_address, self.get_eth_address());
// total_payout
// }

#[feature("safe_dispatcher")]
fn settle_option_round_expect_error(ref self: VaultFacade, error: felt252) {
set_contract_address(bystander());
let safe_vault = self.get_safe_dispatcher();
safe_vault.settle_round().expect_err(error);
}
// #[feature("safe_dispatcher")]
// fn settle_option_round_expect_error(ref self: VaultFacade, error: felt252) {
// set_contract_address(bystander());
// let safe_vault = self.get_safe_dispatcher();
// safe_vault.settle_round().expect_err(error);
// }

/// Fossil

Expand Down
35 changes: 23 additions & 12 deletions src/tests/utils/helpers/accelerators.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use starknet::{
use core::fmt::Display;
use pitch_lake::{
vault::{contract::Vault, interface::{VaultType, IVaultDispatcher, IVaultDispatcherTrait}},
fossil_client::interface::{L1Data, JobRequest, FossilResult},
fossil_client::interface::{L1Data, JobRequest, FossilResult, FossilCallbackReturn, RoundSettledReturn},
option_round::{
contract::{OptionRound},
interface::{
Expand All @@ -24,7 +24,7 @@ use pitch_lake::{
helpers::{ // accelerators::{accelerate_to_auction_custom_auction_params},
event_helpers::{clear_event_logs,},
general_helpers::{to_gwei, assert_two_arrays_equal_length, get_erc20_balances},
//setup::{deploy_custom_option_round},
setup::{eth_supply_and_approve_all_bidders},
},
facades::{
option_round_facade::{OptionRoundFacade, OptionRoundFacadeTrait},
Expand Down Expand Up @@ -99,13 +99,24 @@ fn accelerate_to_settled_custom(ref self: VaultFacade, l1_data: L1Data) -> u256

// Make callback to fulfill the request
timeskip_to_settlement_date(ref self);
self
clear_event_logs(array![self.contract_address()]);

let callback_return = self
.get_fossil_client_facade()
.fossil_callback(request_serialized.span(), result_serialized.span());

let round_settled_return = match callback_return {
FossilCallbackReturn::RoundSettled(total_payout) => {
total_payout
},
_ => panic!("Expected RoundSettled return")
};

clear_event_logs(array![self.contract_address()]);
// Jump to the option expiry date and settle the round
self.settle_option_round()
// Set the ETH allowance for the next round
let current_round_address = self.get_option_round_address(self.get_current_round_id());
eth_supply_and_approve_all_bidders(current_round_address, self.get_eth_address());

round_settled_return.total_payout
}

// Settle the option round with a custom settlement price (compared to strike to determine payout)
Expand Down Expand Up @@ -182,10 +193,10 @@ fn timeskip_and_end_auction(ref self: VaultFacade) -> (u256, u256) {
}

// Jump to the option expriry date and settle the round
fn timeskip_and_settle_round(ref self: VaultFacade) -> u256 {
let mut current_round = self.get_current_round();
set_block_timestamp(current_round.get_option_settlement_date());
set_contract_address(bystander());
self.settle_option_round()
}
// fn timeskip_and_settle_round(ref self: VaultFacade) -> u256 {
// let mut current_round = self.get_current_round();
// set_block_timestamp(current_round.get_option_settlement_date());
// set_contract_address(bystander());
// self.settle_option_round()
// }

27 changes: 27 additions & 0 deletions src/tests/utils/helpers/fossil_client_helpers.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use pitch_lake::fossil_client::interface::{L1Data, JobRequest, FossilResult};
use pitch_lake::tests::utils::facades::vault_facade::{VaultFacade, VaultFacadeTrait};
use pitch_lake::tests::utils::helpers::general_helpers::to_gwei;

fn get_mock_l1_data() -> L1Data {
L1Data { twap: to_gwei(33) / 100, volatility: 1009, reserve_price: to_gwei(11) / 10 }
}

fn get_mock_result() -> FossilResult {
FossilResult { proof: array![].span(), l1_data: get_mock_l1_data() }
}

fn get_mock_result_serialized() -> Span<felt252> {
let mut result_serialized = array![];
get_mock_result().serialize(ref result_serialized);
result_serialized.span()
}

fn get_request(ref vault: VaultFacade) -> JobRequest {
vault.get_request_to_settle_round()
}

fn get_request_serialized(ref vault: VaultFacade) -> Span<felt252> {
let mut request_serialized = array![];
get_request(ref vault).serialize(ref request_serialized);
request_serialized.span()
}
Loading
Loading