Skip to content

Commit

Permalink
Fossil client callback settles round (#186)
Browse files Browse the repository at this point in the history
* wip: fossil callback settles round

* wip: updating tests

* tests: fix tests by adding future round allowance to settle round accelerator

* undo gas limit update
  • Loading branch information
eugenPtr authored Feb 10, 2025
1 parent 0cd4a82 commit 916330a
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 199 deletions.
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

0 comments on commit 916330a

Please sign in to comment.