Skip to content

Commit

Permalink
Cleanup sync 7 2 matt (#76)
Browse files Browse the repository at this point in the history
* Update option_round.cairo

- update settle option round to use struct for params

- de-structure the state transition params to ensure no values are missed

- added strike price to StartAuctionParams

- Cleaned some comments

* Update vault.cairo

- fixed reserve price/cap level/strike price fetching to use independent getters

- re ordered functions to fit together better

* formatting (scarb fmt)

* updated imports/input args to updated functions

* Update option_round.cairo

- add additional bidding error

- added comments

* Update vault.cairo

- added comments

- re-org function order to have similar functions together
  • Loading branch information
0xDegenDeveloper authored Jul 3, 2024
1 parent 66b1957 commit 880fc77
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 69 deletions.
53 changes: 38 additions & 15 deletions src/contracts/option_round.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use openzeppelin::token::erc20::interface::IERC20Dispatcher;
use pitch_lake_starknet::contracts::{
market_aggregator::{IMarketAggregatorDispatcher, IMarketAggregatorDispatcherTrait},
option_round::OptionRound::{
OptionRoundState, StartAuctionParams, OptionRoundConstructorParams, Bid
OptionRoundState, StartAuctionParams, SettleOptionRoundParams, OptionRoundConstructorParams,
Bid,
},
};

Expand Down Expand Up @@ -127,7 +128,7 @@ trait IOptionRound<TContractState> {
// Settle the option round if past the expiry date and in state::Running
// @return The total payout of the option round
fn settle_option_round(
ref self: TContractState, settlement_price: u256
ref self: TContractState, params: SettleOptionRoundParams
) -> Result<u256, OptionRound::OptionRoundError>;

/// Option bidder functions
Expand Down Expand Up @@ -241,12 +242,13 @@ mod OptionRound {
struct StartAuctionParams {
total_options_available: u256,
starting_liquidity: u256,
reserve_price:u256,
cap_level:u256,
reserve_price: u256,
cap_level: u256,
strike_price: u256,
}

#[derive(Copy, Drop, Serde, starknet::Store, PartialEq)]
struct SettleOptionRound {
struct SettleOptionRoundParams {
settlement_price: u256
}

Expand Down Expand Up @@ -407,6 +409,7 @@ mod OptionRound {
OptionSettlementDateNotReached,
// Placing bids
BidBelowReservePrice,
BiddingWhileNotAuctioning,
// Editing bids
BidCannotBeDecreased: felt252,
}
Expand All @@ -422,6 +425,7 @@ mod OptionRound {
OptionRoundError::OptionSettlementDateNotReached => 'OptionRound: Option settle fail',
OptionRoundError::OptionRoundAlreadySettled => 'OptionRound: Option settle fail',
OptionRoundError::BidBelowReservePrice => 'OptionRound: Bid below reserve',
OptionRoundError::BiddingWhileNotAuctioning => 'OptionRound: No auction running',
OptionRoundError::BidCannotBeDecreased(input) => if input == 'amount' {
'OptionRound: Bid amount too low'
} else if input == 'price' {
Expand Down Expand Up @@ -540,6 +544,9 @@ mod OptionRound {
100
}


// @note, not needed, can just use get_bids_for, the state of the round will determine if
// these bids are pending or not
fn get_pending_bids_for(
self: @ContractState, option_buyer: ContractAddress
) -> Array<felt252> {
Expand Down Expand Up @@ -623,21 +630,32 @@ mod OptionRound {
return Result::Err(OptionRoundError::AuctionAlreadyStarted);
}

let StartAuctionParams { total_options_available,
starting_liquidity,
reserve_price,
cap_level,
strike_price } =
params;

// Assert now is >= auction start date
let now = get_block_timestamp();
let start_date = self.get_auction_start_date();
// Assert block timestamp is >= auction start date
if (now < start_date) {
return Result::Err(OptionRoundError::AuctionStartDateNotReached);
}

self.reserve_price.write(params.reserve_price);
self.cap_level.write(params.cap_level);
// Set auction params
self.reserve_price.write(reserve_price);
self.cap_level.write(cap_level);
self.strike_price.write(strike_price);
// Set starting liquidity & total options available
self.starting_liquidity.write(params.starting_liquidity);
self.total_options_available.write(params.total_options_available);
self.starting_liquidity.write(starting_liquidity);
self.total_options_available.write(total_options_available);

// Update state to Auctioning
self.state.write(OptionRoundState::Auctioning);

// Update auction end date if the auction starts later than expected
self.auction_end_date.write(self.auction_end_date.read() + now - start_date);

// Emit auction start event
Expand All @@ -663,16 +681,19 @@ mod OptionRound {
return Result::Err(OptionRoundError::NoAuctionToEnd);
}

// Assert now is >= auction end date
let now = get_block_timestamp();
let end_date = self.get_auction_end_date();
// Assert block timestamp is >= auction end date
if (now < end_date) {
return Result::Err(OptionRoundError::AuctionEndDateNotReached);
}

// Update state to Running
self.state.write(OptionRoundState::Running);

// Update option settlement date if the auction ends later than expected
self.option_settlement_date.write(self.option_settlement_date.read() + now - end_date);

// Calculate clearing price & total options sold
// - An empty helper function is fine for now, we will discuss the
// implementation of this function later
Expand All @@ -695,15 +716,16 @@ mod OptionRound {
}

fn settle_option_round(
ref self: ContractState, settlement_price: u256
ref self: ContractState, params: SettleOptionRoundParams
) -> Result<u256, OptionRoundError> {
// Assert caller is Vault
if (!self.is_caller_the_vault()) {
return Result::Err(OptionRoundError::CallerIsNotVault);
}

// Assert block timestamp is >= option settlement date
if (get_block_timestamp() < self.get_option_settlement_date()) {
// Assert now is >= option settlement date
let now = get_block_timestamp();
if (now < self.get_option_settlement_date()) {
return Result::Err(OptionRoundError::OptionSettlementDateNotReached);
}

Expand All @@ -716,6 +738,7 @@ mod OptionRound {
self.state.write(OptionRoundState::Settled);

// Calculate and set total payout
let SettleOptionRoundParams { settlement_price } = params;
let total_payout = self.calculate_expected_payout(settlement_price);
self.total_payout.write(total_payout);

Expand Down Expand Up @@ -796,7 +819,7 @@ mod OptionRound {
let k = self.get_strike_price();
let cl = self.get_cap_level();
//max(0, min((1 + cl) * k, settlement_price) - k)
// remove sub overflow possibility
// @dev This removes sub overflow possibility
let min = min((1 + cl) * k, settlement_price);
if min > k {
min - k
Expand Down
99 changes: 58 additions & 41 deletions src/contracts/vault.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ trait IVault<TContractState> {
// Get the round transition period
fn get_round_transition_period(self: @TContractState) -> u64;

// @note Add getters for auction run time & option run time
// - need to also add to facade, then use in tests for the (not yet created) setters (A1.1)

/// Rounds

// @return the current option round id
Expand Down Expand Up @@ -68,6 +71,11 @@ trait IVault<TContractState> {

// Get the total premium LP has earned in the current round
// @note premiums for previous rounds
// @note, not sure this function is easily implementable, if a user accuates their position, the
// storage mappings would not be able to correclty value the position in the round_id, to know the
// amount of premiums earned in the round_id. We would need to modify the checkpoints to be a mapping
// instead of a single value (i.e. checkpoint 1 == x, checkpoint 2 == y, along with keeping track of
// the checkpoint nonces)
fn get_premiums_earned(
self: @TContractState, liquidity_provider: ContractAddress, round_id: u256
) -> u256;
Expand Down Expand Up @@ -112,6 +120,8 @@ trait IVault<TContractState> {

/// LP token related

// Phase C ?

// LP converts their collateral into LP tokens
// @note all at once or can LP convert a partial amount ?
// - logically i'm pretty sure they could do a partial amount (collecting all rewards in either case)
Expand Down Expand Up @@ -155,7 +165,7 @@ mod Vault {
OptionRound,
OptionRound::{
OptionRoundErrorIntoFelt252, OptionRoundConstructorParams, StartAuctionParams,
OptionRoundState
SettleOptionRoundParams, OptionRoundState
},
IOptionRoundDispatcher, IOptionRoundDispatcherTrait,
},
Expand Down Expand Up @@ -233,7 +243,6 @@ mod Vault {
round_transition_period: u64,
auction_run_time: u64,
option_run_time: u64,
// liquidity_positions: LegacyMap<((ContractAddress, u256), u256)>,
}

// @note Need to add eth address as a param here
Expand Down Expand Up @@ -445,10 +454,21 @@ mod Vault {
let total_options_available = self
.calculate_total_options_available(starting_liquidity);

let (reserve_price,cap_level)= self.calculate_reserve_cap_price();
// @note replace with individual getters, add strike price
let reserve_price = self.fetch_reserve_price();
let cap_level = self.fetch_cap_level();
let strike_price = self.fetch_strike_price();
// Try to start the auction on the current round
let res = current_round
.start_auction(StartAuctionParams { total_options_available, starting_liquidity,reserve_price, cap_level });
.start_auction(
StartAuctionParams {
total_options_available,
starting_liquidity,
reserve_price,
cap_level,
strike_price
}
);
match res {
Result::Ok(total_options_available) => {
// Update total_locked_liquidity
Expand Down Expand Up @@ -524,7 +544,8 @@ mod Vault {
let settlement_price = self.fetch_settlement_price();

// Try to settle the option round
let res = current_round_dispatcher.settle_option_round(settlement_price);
let res = current_round_dispatcher
.settle_option_round(SettleOptionRoundParams { settlement_price });
match res {
Result::Ok(total_payout) => {
// @dev Checking if payout > 0 to save gas if there is no payout
Expand Down Expand Up @@ -721,25 +742,6 @@ mod Vault {
IOptionRoundDispatcher { contract_address: round_address }
}

fn calculate_reserve_cap_price(ref self:ContractState)-> (u256,u256){
(1,1)
}

fn calculate_total_options_available(
self: @ContractState, starting_liquidity: u256
) -> u256 {
//Calculate total options accordingly
0
}

fn fetch_settlement_price(self: @ContractState) -> u256 {
0
}

fn fetch_settlement_data(self: @ContractState) -> (u256, u256, u256) {
(1, 1, 1)
}

// Deploy the next option round contract, update the current round id & round address mapping
fn deploy_next_round(ref self: ContractState) {
// The round id for the next round
Expand All @@ -759,11 +761,9 @@ mod Vault {
calldata.append_serde(auction_end_date);
calldata.append_serde(option_settlement_date);
// Reserve price, cap level, & strike price
let (reserve_price, strike_price, cap_level) = self
.fetch_reserve_price_cap_level_and_strike_price();
calldata.append_serde(reserve_price);
calldata.append_serde(cap_level);
calldata.append_serde(strike_price);
calldata.append_serde(self.fetch_reserve_price());
calldata.append_serde(self.fetch_cap_level());
calldata.append_serde(self.fetch_strike_price());

// Deploy the next option round contract
let (next_round_address, _) = deploy_syscall(
Expand All @@ -784,18 +784,6 @@ mod Vault {
);
}

// Function to return the reserve price, strike price, and cap level for the upcoming round
// from Fossil
// @return (reserve_price, cap_level, strike_price)
// @note Needs implementation
// @note Fetch values upon deployment, if there are newer (less stale) vaules at the time of auction start,
// we use the newer values to set the params
fn fetch_reserve_price_cap_level_and_strike_price(
ref self: ContractState
) -> (u256, u256, u256) {
(1, 2, 3)
}

// Helper function to return the liquidity provider's unlocked balance broken up into its components
// @return (previous_round_remaining_balance, current_round_collectable_balance, upcoming_round_deposit)
// @dev A user's unlocked balance could be a combination of their: remaining balance at the end of the previous round,
Expand Down Expand Up @@ -931,5 +919,34 @@ mod Vault {
_ => current_round_id + 1
}
}

// Functions to return the reserve price, strike price, and cap level for the upcoming round
// from Fossil
// @note Fetch values upon deployment, if there are newer (less stale) vaules at the time of auction start,
// we use the newer values to set the params
// Phase F (fossil)

fn fetch_reserve_price(self: @ContractState) -> u256 {
1
}

fn fetch_cap_level(self: @ContractState) -> u256 {
1
}

fn fetch_strike_price(self: @ContractState) -> u256 {
1
}

fn fetch_settlement_price(self: @ContractState) -> u256 {
0
}

fn calculate_total_options_available(
self: @ContractState, starting_liquidity: u256
) -> u256 {
//Calculate total options accordingly
0
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ fn test_only_vault_can_start_auction() {

set_contract_address(other_vault.contract_address());

next_round.start_auction(StartAuctionParams{total_options_available:1,starting_liquidity:1,reserve_price:123,cap_level: 123});
next_round
.start_auction(
StartAuctionParams {
total_options_available: 1,
starting_liquidity: 1,
reserve_price: 123,
cap_level: 123,
strike_price: 123,
}
);
}

// @note Modify to check the Result of the function to be Result::Err(e)
Expand Down
15 changes: 6 additions & 9 deletions src/tests/utils/facades/option_round_facade.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use starknet::{ContractAddress, testing::{set_contract_address}};
use pitch_lake_starknet::{
contracts::option_round::{
IOptionRoundDispatcher, IOptionRoundDispatcherTrait, OptionRoundState, StartAuctionParams,
OptionRoundConstructorParams, Bid,
SettleOptionRoundParams, OptionRoundConstructorParams, Bid,
OptionRound::{
OptionRoundError, OptionRoundErrorIntoFelt252, //OptionRoundErrorIntoByteArray
}
Expand Down Expand Up @@ -35,13 +35,8 @@ impl OptionRoundFacadeImpl of OptionRoundFacadeTrait {
// to test this.

// Start the next option round's auction
fn start_auction(
ref self: OptionRoundFacade, params:StartAuctionParams,
) -> u256 {

let res = self
.option_round_dispatcher
.start_auction(params);
fn start_auction(ref self: OptionRoundFacade, params: StartAuctionParams,) -> u256 {
let res = self.option_round_dispatcher.start_auction(params);
match res {
Result::Ok(total_options_available) => sanity_checks::start_auction(
ref self, total_options_available
Expand All @@ -63,7 +58,9 @@ impl OptionRoundFacadeImpl of OptionRoundFacadeTrait {

// Settle the current option round
fn settle_option_round(ref self: OptionRoundFacade, settlement_price: u256) -> u256 {
let res = self.option_round_dispatcher.settle_option_round(settlement_price);
let res = self
.option_round_dispatcher
.settle_option_round(SettleOptionRoundParams { settlement_price });
match res {
Result::Ok(total_payout) => sanity_checks::settle_option_round(ref self, total_payout),
Result::Err(e) => panic(array![e.into()]),
Expand Down
Loading

0 comments on commit 880fc77

Please sign in to comment.