diff --git a/src/arbitrary_proposal_add_options.cairo b/src/arbitrary_proposal_add_options.cairo new file mode 100644 index 0000000..36fa62b --- /dev/null +++ b/src/arbitrary_proposal_add_options.cairo @@ -0,0 +1,49 @@ +use starknet::contract_address::{ContractAddress}; + +#[starknet::interface] +trait IArbitraryProposalAddOptions { + fn execute_arbitrary_proposal(ref self: TContractState); +} + +#[starknet::contract] +pub mod ArbitraryProposalAddOptions { + use amm_governance::proposals::proposals as proposals_component; + use amm_governance::proposals::proposals::InternalTrait; + use konoha::contract::IGovernanceDispatcher; + use konoha::contract::IGovernanceDispatcherTrait; + use konoha::types::{CustomProposalConfig}; + use starknet::{ContractAddress, ClassHash, get_contract_address}; + + component!(path: proposals_component, storage: proposals, event: ProposalsEvent); + + #[storage] + struct Storage { + #[substorage(v0)] + proposals: proposals_component::Storage, + } + + #[derive(starknet::Event, Drop)] + #[event] + enum Event { + ProposalsEvent: proposals_component::Event, + } + + #[constructor] + fn constructor(ref self: ContractState) {} + + #[abi(embed_v0)] + impl ArbitraryProposalAddOptions of super::IArbitraryProposalAddOptions { + fn execute_arbitrary_proposal(ref self: ContractState) { + let option_deployer_class_hash: felt252 = + 0x004e19b87b7777e6e7032ca325794cd793a4d6e9591a8c4e60e0d1b27e4da3d7; + + let add_options = CustomProposalConfig { + target: option_deployer_class_hash, + selector: selector!("add_options"), + library_call: true + }; + + self.proposals.add_custom_proposal_config(add_options); + } + } +} diff --git a/src/lib.cairo b/src/lib.cairo index 605cd6a..c21225c 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,10 +1,11 @@ +mod arbitrary_proposal_add_options; pub mod carm; pub mod constants; pub mod contract; mod options; pub mod proposals; pub mod staking; -mod traits; -mod types; +pub mod traits; +pub mod types; mod upgrades; pub mod vecarm; diff --git a/src/traits.cairo b/src/traits.cairo index c0108d6..844e727 100644 --- a/src/traits.cairo +++ b/src/traits.cairo @@ -1,4 +1,4 @@ -use amm_governance::types::{OptionType, OptionSide}; +use amm_governance::types::{OptionType, OptionSide, Option_}; use cubit::f128::types::{Fixed, FixedTrait}; use starknet::{ContractAddress, ClassHash}; @@ -87,7 +87,7 @@ pub trait IAMM { self: @TContractState, lptoken_addr: ContractAddress, lpt_amt: u256 ) -> u256; fn get_available_lptoken_addresses(self: @TContractState, order_i: felt252) -> ContractAddress; - // fn get_all_options(self: @TContractState, lptoken_address: ContractAddress) -> Array; + fn get_all_options(self: @TContractState, lptoken_address: ContractAddress) -> Array; // fn get_all_non_expired_options_with_premia( // self: @TContractState, lptoken_address: ContractAddress // ) -> Array; @@ -211,6 +211,7 @@ pub trait IAMM { fn set_pragma_checkpoint(ref self: TContractState, key: felt252); fn set_pragma_required_checkpoints(ref self: TContractState); fn upgrade(ref self: TContractState, new_implementation: ClassHash); + fn transfer_ownership(ref self: TContractState, new_owner: ContractAddress); } #[starknet::interface] diff --git a/src/types.cairo b/src/types.cairo index 33e06d0..ed197f7 100644 --- a/src/types.cairo +++ b/src/types.cairo @@ -17,3 +17,13 @@ pub struct FutureOption { pub base_token_address: ContractAddress, pub initial_volatility: Fixed } + +#[derive(Copy, Drop, Serde)] +pub struct Option_ { + pub option_side: OptionSide, + pub maturity: u64, + pub strike_price: Fixed, + pub quote_token_address: ContractAddress, + pub base_token_address: ContractAddress, + pub option_type: OptionType +} diff --git a/tests/add_options_proposal.cairo b/tests/add_options_proposal.cairo new file mode 100644 index 0000000..b5b7149 --- /dev/null +++ b/tests/add_options_proposal.cairo @@ -0,0 +1,179 @@ +use amm_governance::proposals::{IProposalsDispatcherTrait, IProposalsDispatcher}; +use amm_governance::traits::{IAMMDispatcher, IAMMDispatcherTrait}; +use amm_governance::types::Option_; + +use konoha::upgrades::IUpgradesDispatcher; +use konoha::upgrades::IUpgradesDispatcherTrait; +use snforge_std::{ + CheatSpan, CheatTarget, ContractClassTrait, ContractClass, prank, start_warp, declare +}; + +use starknet::{ContractAddress, get_block_timestamp}; + +fn get_voter_addresses() -> @Span { + let arr = array![ + 0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233, + 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1, + 0x03d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad, + 0x00d79a15d84f5820310db21f953a0fae92c95e25d93cb983cc0c27fc4c52273c, + 0x0428c240649b76353644faF011B0d212e167f148fdd7479008Aa44eEaC782BfC, + 0x06717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af, + ]; + @arr.span() +} + +fn get_option_calldata() -> @Span { + // calldata generated by FE + let arr = array![ + 0x047472e6755afc57ada9550b6a3ac93129cc4b5f98f51c73e0644d129fd208d9, //amm address ! + 0x2, // array length + 0x5354524b2d555344432d43414c4c2d4c4f4e47, // str_to_felt STRK-USDC-CALL-LONG + 0x5354524b2d555344432d43414c4c2d53484f5254, // str_to_felt STRK-USDC-CALL-SHORT + 0x675B78FF, // maturity + 0x6666666666666666, // strike price 0.4 + 0x0, // fixed sign + 0x0, // option type + 0x2b629088a1d30019ef18b893cebab236f84a365402fa0df2f51ec6a01506b1d, // lp address + 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8, // quote address + 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d, // base address + 0x5a0000000000000000, // volatility + 0x0, // fixed sign + 0x5354524b2d555344432d43414c4c2d4c4f4e47, // str_to_felt STRK-USDC-CALL-LONG + 0x5354524b2d555344432d43414c4c2d53484f5254, // str_to_felt STRK-USDC-CALL-SHORT + 0x675B78FF, // maturity + 0x8000000000000000, // strike price 0.5 + 0x0, // fixed sign + 0x0, // option type + 0x2b629088a1d30019ef18b893cebab236f84a365402fa0df2f51ec6a01506b1d, // lp address + 0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8, // quote address + 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d, // base address + 0x5a0000000000000000, + 0x0, + ]; + @arr.span() +} + +#[test] +#[fork("MAINNET")] +fn test_add_custom_proposal() { + // # ADD CUSTOM PROPOSAL FOR ADDING OPTIONS + + let gov_addr = 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f + .try_into() + .unwrap(); + let props = IProposalsDispatcher { contract_address: gov_addr }; + + let user1: ContractAddress = + 0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233 // team m 1 + .try_into() + .unwrap(); + + let prop_id = 103; + + let mut voter_addresses = *get_voter_addresses(); + + // vote yay with all users + loop { + match voter_addresses.pop_front() { + Option::Some(address) => { + let current_voter: ContractAddress = (*address).try_into().unwrap(); + prank(CheatTarget::One(gov_addr), current_voter, CheatSpan::TargetCalls(1)); + props.vote(prop_id, 1); + }, + Option::None(()) => { break (); } + } + }; + + let curr_timestamp = get_block_timestamp(); + let proposal_wait_time = consteval_int!(60 * 60 * 24 * 7) + 420; + let warped_timestamp = curr_timestamp + proposal_wait_time; + + start_warp(CheatTarget::One(gov_addr), warped_timestamp); + assert(props.get_proposal_status(prop_id) == 1, 'arbitrary proposal not passed'); + + let upgrades = IUpgradesDispatcher { contract_address: gov_addr }; + + upgrades.apply_passed_proposal(prop_id); + + println!("custom proposal added"); + + // # TRANSFER OWNERSHIP OF AMM + + let amm_owner_address: ContractAddress = + 0x74fd7da23e21f0f0479adb435221b23f57ca4c32a0c68aad9409a41c27f3067 + .try_into() + .unwrap(); + let amm_address: ContractAddress = + 0x047472e6755afc57ada9550b6a3ac93129cc4b5f98f51c73e0644d129fd208d9 + .try_into() + .unwrap(); + let amm = IAMMDispatcher { contract_address: amm_address }; + + prank(CheatTarget::One(amm_address), amm_owner_address, CheatSpan::TargetCalls(1)); + amm.transfer_ownership(gov_addr); + + println!("AMM ownership transfered"); + + // # ADD OPTIONS VIA NEW CUSTOM PROPOSAL + + let add_options_calldata = get_option_calldata(); + + println!("add options calldata: {:?}", add_options_calldata); + + prank(CheatTarget::One(gov_addr), user1, CheatSpan::TargetCalls(1)); + // propose arbitrary proposal + let prop_id2: felt252 = props.submit_custom_proposal(0x2, *add_options_calldata).into(); + + let mut voter_addresses2 = *get_voter_addresses(); + + // vote yay with all users + loop { + match voter_addresses2.pop_front() { + Option::Some(address) => { + let current_voter: ContractAddress = (*address).try_into().unwrap(); + prank(CheatTarget::One(gov_addr), current_voter, CheatSpan::TargetCalls(1)); + props.vote(prop_id2, 1); + }, + Option::None(()) => { break (); } + } + }; + + let warped_timestamp2 = curr_timestamp + proposal_wait_time * 2; + + start_warp(CheatTarget::One(gov_addr), warped_timestamp2); + assert(props.get_proposal_status(prop_id2) == 1, 'add options not passed'); + println!("add options passed"); + + upgrades.apply_passed_proposal(prop_id2); + + println!("options added"); + + // # VALIDATED THAT CORRECT OPTIONS WERE ADDED + + let strk_usdc_call_lp_address: ContractAddress = + 0x2b629088a1d30019ef18b893cebab236f84a365402fa0df2f51ec6a01506b1d + .try_into() + .unwrap(); + let mut all_strk_usdc_call_options: Array = amm + .get_all_options(strk_usdc_call_lp_address); + + // TODO: validate that the options that were added are there + loop { + match all_strk_usdc_call_options.pop_front() { + Option::Some(option) => { + // only print the new options + if option.maturity == 1734047999 { + // TODO: right now just read it from the console + println!("OPTION"); + println!("strike: {:?}", option.strike_price.mag); + println!("quote: {:?}", option.quote_token_address); + println!("base: {:?}", option.base_token_address); + println!("type: {:?}", option.option_type); + println!("side: {:?}", option.option_side); + println!("maturity: {:?}", option.maturity); + } + }, + Option::None(()) => { break (); } + } + }; +} diff --git a/tests/lib.cairo b/tests/lib.cairo index 038e712..337869a 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,3 +1,4 @@ +mod add_options_proposal; mod test_prop_pass; //mod unstake_airdrop; //mod add_options; diff --git a/tests/upgrade.cairo b/tests/upgrade.cairo index e7114a4..3fcff33 100644 --- a/tests/upgrade.cairo +++ b/tests/upgrade.cairo @@ -176,7 +176,7 @@ fn scenario_airdrop_staked_carm() { 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1 // team .try_into() .unwrap(); - let investor1: ContractAddress = + let _investor1: ContractAddress = 0x056d761e1e5d1918dba05de02afdbd8de8da01a63147dce828c9b1fe9227077d .try_into() .unwrap();