From ab60119c26427a6077e9bd8e24a9104b69a5fa09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sojka?= <8470346+tensojka@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:45:16 +0100 Subject: [PATCH] Migrate to Cairo 2.3.1 & Components (#26) * Update Scarb to 2.3.0 * Update to Scarb 2.3.1 * Add Scarb.lock * Refactor airdrop to be its own Component * WIP * Fix syntax, use new * Remove vote_investor as it's Carmine only * Migrate main contract file * Finish migration * Add CI * Fix scarb version in CI * Format --- .devcontainer/devcontainer.json | 2 +- .github/workflows/ci.yml | 11 +- Scarb.lock | 6 + src/airdrop.cairo | 98 +++++++----- src/contract.cairo | 32 ++-- src/merkle_tree.cairo | 4 +- src/options.cairo | 36 ++--- src/proposals.cairo | 272 ++++++++------------------------ src/traits.cairo | 8 +- src/upgrades.cairo | 42 +++-- 10 files changed, 180 insertions(+), 331 deletions(-) create mode 100644 Scarb.lock diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ab75162f..9431f7cc 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,7 @@ // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 0.6.2", + "postCreateCommand": "curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v 2.3.1", "customizations": { "vscode": { "extensions": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65690f1c..0b1e0a42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,8 +7,7 @@ on: - '.github/' env: - LINK: https://github.com/software-mansion/scarb/releases/download/v0.6.2/scarb-v0.6.2-x86_64-unknown-linux-gnu.tar.gz - NAME: scarb-v0.6.2-x86_64-unknown-linux-gnu + SCARB_VERSION: 2.3.1 jobs: build: @@ -16,12 +15,8 @@ jobs: steps: - name: Checkout (GitHub) uses: actions/checkout@v3 - - name: Download binaries - run: curl -L -o $NAME.tar.gz $LINK - - name: Prepare binaries - run: tar -xvf $NAME.tar.gz - - name: Make binaries available - run: echo "./$NAME/bin" >> $GITHUB_PATH + - name: Install Scarb + run: curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v $SCARB_VERSION - name: Check formatting run: scarb fmt --check - name: Build with scarb diff --git a/Scarb.lock b/Scarb.lock new file mode 100644 index 00000000..14bb4a9d --- /dev/null +++ b/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "governance" +version = "0.2.0" diff --git a/src/airdrop.cairo b/src/airdrop.cairo index 2abf8cb8..b9a934ff 100644 --- a/src/airdrop.cairo +++ b/src/airdrop.cairo @@ -1,12 +1,23 @@ // https://github.com/CarmineOptions/carmine-api/blob/master/carmine-api-airdrop/src/merkle_tree.rs -mod Airdrop { +use starknet::ContractAddress; + +#[starknet::interface] +trait IAirdrop { + fn claim( + ref self: TContractState, claimee: ContractAddress, amount: u128, proof: Array:: + ); +} + +#[starknet::component] +mod airdrop { + use governance::contract::IGovernance; use array::ArrayTrait; use hash::LegacyHash; use traits::Into; - use starknet::ContractAddress; use starknet::ContractAddressIntoFelt252; - use starknet::event::EventEmitter; + use starknet::ContractAddress; + //use starknet::event::EventEmitter; use traits::TryInto; use option::OptionTrait; @@ -14,52 +25,61 @@ mod Airdrop { use governance::merkle_tree::MerkleTreeTrait; use governance::contract::Governance; + use governance::contract::Governance::ContractState; use governance::traits::IGovernanceTokenDispatcher; use governance::traits::IGovernanceTokenDispatcherTrait; - use governance::contract::Governance::{governance_token_address, airdrop_claimed, merkle_root}; - fn get_merkle_root() -> felt252 { - let state = Governance::unsafe_new_contract_state(); - let root = merkle_root::InternalContractStateTrait::read(@state.merkle_root); - if (root == 0) { - // part of migration, to be removed later - 0x6d5f4866e61240e8f14de3d5c994153b1bcbf58603f64fa1a0500074b8c8d38 // airdrop week5-week8, from round_2_composed.csv - } else { - root - } + #[storage] + struct Storage { + airdrop_claimed: LegacyMap::, + merkle_root: felt252 } - // Lets claimee claim from merkle tree the amount - claimed_so_far - fn claim(claimee: ContractAddress, amount: u128, proof: Array::) { - let mut state = Governance::unsafe_new_contract_state(); + #[derive(starknet::Event, Drop)] + #[event] + enum Event { + Claimed: Claimed + } - let mut merkle_tree = MerkleTreeTrait::new(); - let amount_felt: felt252 = amount.into(); - let leaf = LegacyHash::hash(claimee.into(), amount_felt); + #[derive(starknet::Event, Drop)] + struct Claimed { + address: ContractAddress, + received: u128 + } + #[embeddable_as(AirdropImpl)] + impl Airdrop< + TContractState, +HasComponent + > of super::IAirdrop> { + // Lets claimee claim from merkle tree the amount - claimed_so_far + fn claim( + ref self: ComponentState, + claimee: ContractAddress, + amount: u128, + proof: Array:: + ) { + let mut merkle_tree = MerkleTreeTrait::new(); + let amount_felt: felt252 = amount.into(); + let leaf = LegacyHash::hash(claimee.into(), amount_felt); - let root = merkle_tree.compute_root(leaf, proof.span()); - assert(root == get_merkle_root(), 'invalid proof'); + let root = merkle_tree.compute_root(leaf, proof.span()); + let state = Governance::unsafe_new_contract_state(); + let stored_root = self.merkle_root.read(); + assert(root == stored_root, 'invalid proof'); - let claimed_so_far: u128 = airdrop_claimed::InternalContractStateTrait::read( - @state.airdrop_claimed, claimee - ); - assert(claimed_so_far < amount, 'claiming more than eligible for'); - let to_mint = amount - claimed_so_far; + let claimed_so_far: u128 = self.airdrop_claimed.read(claimee); + assert(claimed_so_far < amount, 'claiming more than eligible for'); + let to_mint = amount - claimed_so_far; - // Mint - let govtoken_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - IGovernanceTokenDispatcher { - contract_address: govtoken_addr - }.mint(claimee, u256 { high: 0, low: to_mint }); + // Mint + let govtoken_addr = state.get_governance_token_address(); + IGovernanceTokenDispatcher { contract_address: govtoken_addr } + .mint(claimee, u256 { high: 0, low: to_mint }); - // Emit event - state.emit(Governance::Claimed { address: claimee, received: to_mint }); + // Write new claimed amt + self.airdrop_claimed.write(claimee, to_mint + claimed_so_far); - // Write new claimed amt - airdrop_claimed::InternalContractStateTrait::write( - ref state.airdrop_claimed, claimee, to_mint + claimed_so_far - ); + // Emit event + self.emit(Claimed { address: claimee, received: to_mint }); + } } } diff --git a/src/contract.cairo b/src/contract.cairo index 85f1686b..558f45d2 100644 --- a/src/contract.cairo +++ b/src/contract.cairo @@ -24,9 +24,7 @@ trait IGovernance { // AIRDROPS - fn claim( - ref self: TContractState, address: ContractAddress, amount: u128, proof: Array:: - ); + // in component // OPTIONS @@ -42,11 +40,17 @@ mod Governance { use governance::types::ContractType; use governance::types::PropDetails; use governance::upgrades::Upgrades; - use governance::airdrop::Airdrop; use governance::options::Options; + use governance::airdrop::airdrop as airdrop_component; use starknet::ContractAddress; + + component!(path: airdrop_component, storage: airdrop, event: AirdropEvent); + + #[abi(embed_v0)] + impl Airdrop = airdrop_component::AirdropImpl; + #[storage] struct Storage { proposal_details: LegacyMap::, @@ -60,10 +64,10 @@ mod Governance { total_investor_distributed_power: felt252, governance_token_address: ContractAddress, amm_address: ContractAddress, - airdrop_claimed: LegacyMap::, delegate_hash: LegacyMap::, total_delegated_to: LegacyMap::, - merkle_root: felt252 + #[substorage(v0)] + airdrop: airdrop_component::Storage } // PROPOSALS @@ -82,18 +86,12 @@ mod Governance { opinion: VoteStatus } - #[derive(starknet::Event, Drop)] - struct Claimed { - address: ContractAddress, - received: u128 - } - #[derive(starknet::Event, Drop)] #[event] enum Event { Proposed: Proposed, Voted: Voted, - Claimed: Claimed + AirdropEvent: airdrop_component::Event } #[constructor] @@ -145,14 +143,6 @@ mod Governance { Upgrades::apply_passed_proposal(prop_id) } - // AIRDROPS - - fn claim( - ref self: ContractState, address: ContractAddress, amount: u128, proof: Array:: - ) { - Airdrop::claim(address, amount, proof) - } - fn add_0911_1611_options(ref self: ContractState) { Options::run_add_0911_1611_options() } diff --git a/src/merkle_tree.cairo b/src/merkle_tree.cairo index 37c80737..06f9ac6d 100644 --- a/src/merkle_tree.cairo +++ b/src/merkle_tree.cairo @@ -62,9 +62,7 @@ impl MerkleTreeImpl of MerkleTreeTrait { current_node = LegacyHash::hash(*proof_element, current_node); } }, - Option::None(()) => { - break current_node; - }, + Option::None(()) => { break current_node; }, }; } } diff --git a/src/options.cairo b/src/options.cairo index e734b62d..dcb44716 100644 --- a/src/options.cairo +++ b/src/options.cairo @@ -3,6 +3,7 @@ // – first generating FutureOption, then generating everything from Pragma data mod Options { + use governance::contract::IGovernance; use traits::{Into, TryInto}; use array::{ArrayTrait, SpanTrait}; use option::OptionTrait; @@ -26,6 +27,7 @@ mod Options { use governance::contract::Governance; use governance::types::OptionType; use governance::traits::Math64x61_; + use governance::contract::Governance::proposal_initializer_runContractMemberStateTrait; // 2**61 = 2305843009213693952 const VOLATILITY_28: Math64x61_ = consteval_int!(28 * 2305843009213693952); @@ -73,7 +75,7 @@ mod Options { // TODO use block hash from block_hash syscall as salt // actually doable with the new syscall let governance_address = get_contract_address(); let state = Governance::unsafe_new_contract_state(); - let amm_address = amm_address::InternalContractStateTrait::read(@state.amm_address); + let amm_address = state.get_amm_address(); let proxy_class: felt252 = 0x00eafb0413e759430def79539db681f8a4eb98cf4196fe457077d694c6aeeb82; let opt_class: felt252 = 0x5ce3a80daeb5b7a766df9b41ca8d9e52b6b0a045a0d2ced72f43d4dd2f93b10; @@ -84,9 +86,7 @@ mod Options { proxy_class, opt_class, governance_address, amm_address, salt, option ); }, - Option::None(()) => { - break (); - }, + Option::None(()) => { break (); }, }; } } @@ -131,9 +131,7 @@ mod Options { proxy_class_hash, opt_class_hash, custom_salt ); - IOptionTokenDispatcher { - contract_address: optoken_long_addr - } + IOptionTokenDispatcher { contract_address: optoken_long_addr } .initializer( o.name_long, 'C-OPT', @@ -147,9 +145,7 @@ mod Options { TRADE_SIDE_LONG ); - IAMMDispatcher { - contract_address: amm_address - } + IAMMDispatcher { contract_address: amm_address } .add_option( TRADE_SIDE_LONG, o.maturity, @@ -166,9 +162,7 @@ mod Options { proxy_class_hash, opt_class_hash, custom_salt + 1 ); - IOptionTokenDispatcher { - contract_address: optoken_short_addr - } + IOptionTokenDispatcher { contract_address: optoken_short_addr } .initializer( o.name_short, 'C-OPT', @@ -182,9 +176,7 @@ mod Options { TRADE_SIDE_SHORT ); - IAMMDispatcher { - contract_address: amm_address - } + IAMMDispatcher { contract_address: amm_address } .add_option( TRADE_SIDE_SHORT, o.maturity, @@ -213,15 +205,9 @@ mod Options { fn run_add_0911_1611_options() { let mut state = Governance::unsafe_new_contract_state(); - assert( - !proposal_initializer_run::InternalContractStateTrait::read( - @state.proposal_initializer_run, 36 - ), - 'prop36 initializer called again' - ); - proposal_initializer_run::InternalContractStateTrait::write( - ref state.proposal_initializer_run, 36, true - ); + assert(!state.proposal_initializer_run.read(36), 'prop already initialized'); + + state.proposal_initializer_run.write(36, true); add_0911_options(); add_1611_options(); diff --git a/src/proposals.cairo b/src/proposals.cairo index 8996213f..548322f5 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -1,4 +1,5 @@ mod Proposals { + use governance::contract::IGovernance; use traits::TryInto; use option::OptionTrait; use traits::Into; @@ -22,18 +23,15 @@ mod Proposals { use starknet::class_hash::class_hash_try_from_felt252; use starknet::contract_address::contract_address_to_felt252; - use governance::contract::Governance::proposal_total_yay; - use governance::contract::Governance::proposal_total_nay; - use governance::contract::Governance::proposal_vote_ends; - use governance::contract::Governance::proposal_details; - use governance::contract::Governance::proposal_voted_by; - use governance::contract::Governance::governance_token_address; - use governance::contract::Governance::investor_voting_power; - use governance::contract::Governance::total_investor_distributed_power; - use governance::contract::Governance::delegate_hash; - use governance::contract::Governance::total_delegated_to; + use governance::contract::Governance::proposal_total_yayContractMemberStateTrait; + use governance::contract::Governance::proposal_total_nayContractMemberStateTrait; + use governance::contract::Governance::proposal_vote_endsContractMemberStateTrait; + use governance::contract::Governance::delegate_hashContractMemberStateTrait; + use governance::contract::Governance::total_delegated_toContractMemberStateTrait; + use governance::contract::Governance::proposal_voted_byContractMemberStateTrait; + use governance::contract::Governance::proposal_detailsContractMemberStateTrait; use governance::contract::Governance::ContractState; - use governance::contract::Governance::unsafe_new_contract_state; // To be removed once Components arrive + use governance::contract::Governance::unsafe_new_contract_state; use governance::contract::Governance; use governance::types::BlockNumber; use governance::types::ContractType; @@ -45,36 +43,15 @@ mod Proposals { fn get_vote_counts(prop_id: felt252) -> (u128, u128) { let state: ContractState = Governance::unsafe_new_contract_state(); - let yay = proposal_total_yay::InternalContractStateTrait::read( - @state.proposal_total_yay, prop_id - ); - let nay = proposal_total_nay::InternalContractStateTrait::read( - @state.proposal_total_nay, prop_id - ); + let yay = state.proposal_total_yay.read(prop_id); + let nay = state.proposal_total_nay.read(prop_id); (yay.try_into().unwrap(), nay.try_into().unwrap()) } fn get_proposal_details(prop_id: felt252) -> PropDetails { let state = Governance::unsafe_new_contract_state(); - proposal_details::InternalContractStateTrait::read(@state.proposal_details, prop_id) - } - - fn get_free_prop_id() -> felt252 { - _get_free_prop_id(0) - } - - fn _get_free_prop_id(currid: felt252) -> felt252 { - let state = Governance::unsafe_new_contract_state(); - let res = proposal_vote_ends::InternalContractStateTrait::read( - @state.proposal_vote_ends, currid - ); - - if res == 0 { - currid - } else { - _get_free_prop_id(currid + 1) - } + state.proposal_details.read(prop_id) } fn assert_correct_contract_type(contract_type: ContractType) { @@ -84,9 +61,7 @@ mod Proposals { fn assert_voting_in_progress(prop_id: felt252) { let state = Governance::unsafe_new_contract_state(); - let end_block_number_felt: felt252 = proposal_vote_ends::InternalContractStateTrait::read( - @state.proposal_vote_ends, prop_id - ); + let end_block_number_felt: felt252 = state.proposal_vote_ends.read(prop_id); let end_block_number: u64 = end_block_number_felt.try_into().unwrap(); assert(end_block_number != 0, 'prop_id not found'); @@ -99,16 +74,28 @@ mod Proposals { u256 { low, high } } + fn get_free_prop_id() -> felt252 { + _get_free_prop_id(0) + } + + fn _get_free_prop_id(currid: felt252) -> felt252 { + let state = Governance::unsafe_new_contract_state(); + let res = state.proposal_vote_ends.read(currid); + if res == 0 { + currid + } else { + _get_free_prop_id(currid + 1) + } + } + fn submit_proposal(payload: felt252, to_upgrade: ContractType) -> felt252 { assert_correct_contract_type(to_upgrade); let mut state = Governance::unsafe_new_contract_state(); - let govtoken_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); + let govtoken_addr = state.get_governance_token_address(); let caller = get_caller_address(); - let caller_balance: u128 = IERC20Dispatcher { - contract_address: govtoken_addr - }.balanceOf(caller).low; + let caller_balance: u128 = IERC20Dispatcher { contract_address: govtoken_addr } + .balanceOf(caller) + .low; let total_supply = IERC20Dispatcher { contract_address: govtoken_addr }.totalSupply(); let res: u256 = as_u256( 0, caller_balance * constants::NEW_PROPOSAL_QUORUM @@ -117,17 +104,13 @@ mod Proposals { let prop_id = get_free_prop_id(); let prop_details = PropDetails { payload: payload, to_upgrade: to_upgrade }; - proposal_details::InternalContractStateTrait::write( - ref state.proposal_details, prop_id, prop_details - ); + state.proposal_details.write(prop_id, prop_details); let current_block_number: u64 = get_block_info().unbox().block_number; let end_block_number: BlockNumber = (current_block_number + constants::PROPOSAL_VOTING_TIME_BLOCKS) .into(); - proposal_vote_ends::InternalContractStateTrait::write( - ref state.proposal_vote_ends, prop_id, end_block_number - ); + state.proposal_vote_ends.write(prop_id, end_block_number); state.emit(Governance::Proposed { prop_id, payload, to_upgrade }); prop_id @@ -190,23 +173,16 @@ mod Proposals { let mut state = Governance::unsafe_new_contract_state(); let caller_addr = get_caller_address(); - let stored_hash = delegate_hash::InternalContractStateTrait::read( - @state.delegate_hash, caller_addr - ); + let stored_hash = state.delegate_hash.read(caller_addr); let calldata_span: Span<(ContractAddress, u128)> = calldata.span(); assert(stored_hash == hashing(0, calldata_span, 0), 'incorrect delegate list'); - let curr_total_delegated_to = total_delegated_to::InternalContractStateTrait::read( - @state.total_delegated_to, to_addr - ); + let curr_total_delegated_to = state.total_delegated_to.read(to_addr); let converted_addr = contract_address_to_felt252(caller_addr); - let gov_token_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - let caller_balance_u256: u256 = IERC20Dispatcher { - contract_address: gov_token_addr - }.balanceOf(caller_addr); + let gov_token_addr = state.get_governance_token_address(); + let caller_balance_u256: u256 = IERC20Dispatcher { contract_address: gov_token_addr } + .balanceOf(caller_addr); assert(caller_balance_u256.high == 0, 'CARM balance > u128'); let caller_balance: u128 = caller_balance_u256.low; assert(caller_balance > 0, 'CARM balance is zero'); @@ -219,12 +195,8 @@ mod Proposals { update_calldata(to_addr, already_delegated + amount, calldata_span, updated_list, 0); - delegate_hash::InternalContractStateTrait::write( - ref state.delegate_hash, caller_addr, hashing(0, updated_list_span, 0) - ); - total_delegated_to::InternalContractStateTrait::write( - ref state.total_delegated_to, to_addr, curr_total_delegated_to + amount - ); + state.delegate_hash.write(caller_addr, hashing(0, updated_list_span, 0)); + state.total_delegated_to.write(to_addr, curr_total_delegated_to + amount); } fn withdraw_delegation( @@ -232,9 +204,7 @@ mod Proposals { ) { let mut state = Governance::unsafe_new_contract_state(); let caller_addr = get_caller_address(); - let stored_hash = delegate_hash::InternalContractStateTrait::read( - @state.delegate_hash, caller_addr - ); + let stored_hash = state.delegate_hash.read(caller_addr); let calldata_span: Span<(ContractAddress, u128)> = calldata.span(); assert(stored_hash == hashing(0, calldata_span, 0), 'incorrect delegate list'); @@ -246,16 +216,10 @@ mod Proposals { let minus_amount = 0 - amount; update_calldata(to_addr, minus_amount, calldata_span, updated_list, 0); - delegate_hash::InternalContractStateTrait::write( - ref state.delegate_hash, caller_addr, hashing(0, updated_list_span, 0) - ); + state.delegate_hash.write(caller_addr, hashing(0, updated_list_span, 0)); - let curr_total_delegated_to = total_delegated_to::InternalContractStateTrait::read( - @state.total_delegated_to, to_addr - ); - total_delegated_to::InternalContractStateTrait::write( - ref state.total_delegated_to, to_addr, curr_total_delegated_to - amount - ); + let curr_total_delegated_to = state.total_delegated_to.read(to_addr); + state.total_delegated_to.write(to_addr, curr_total_delegated_to - amount); } @@ -271,57 +235,35 @@ mod Proposals { let mut state = Governance::unsafe_new_contract_state(); - let gov_token_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); + let gov_token_addr = state.get_governance_token_address(); let caller_addr = get_caller_address(); - let curr_vote_status: felt252 = proposal_voted_by::InternalContractStateTrait::read( - @state.proposal_voted_by, (prop_id, caller_addr) - ); + let curr_vote_status: felt252 = state.proposal_voted_by.read((prop_id, caller_addr)); assert(curr_vote_status == 0, 'already voted'); - let caller_balance_u256: u256 = IERC20Dispatcher { - contract_address: gov_token_addr - }.balanceOf(caller_addr); + let caller_balance_u256: u256 = IERC20Dispatcher { contract_address: gov_token_addr } + .balanceOf(caller_addr); assert(caller_balance_u256.high == 0, 'CARM balance > u128'); let caller_balance: u128 = caller_balance_u256.low; assert(caller_balance != 0, 'CARM balance is zero'); - let caller_voting_power = caller_balance - + total_delegated_to::InternalContractStateTrait::read( - @state.total_delegated_to, caller_addr - ); + let caller_voting_power = caller_balance + state.total_delegated_to.read(caller_addr); assert(caller_voting_power > 0, 'No voting power'); assert_voting_in_progress(prop_id); // Cast vote - proposal_voted_by::InternalContractStateTrait::write( - ref state.proposal_voted_by, (prop_id, caller_addr), actual_opinion - ); + state.proposal_voted_by.write((prop_id, caller_addr), actual_opinion); if actual_opinion == constants::MINUS_ONE { - let curr_votes: u128 = proposal_total_nay::InternalContractStateTrait::read( - @state.proposal_total_nay, prop_id - ) - .try_into() - .unwrap(); + let curr_votes: u128 = state.proposal_total_nay.read(prop_id).try_into().unwrap(); let new_votes: u128 = curr_votes + caller_voting_power; assert(new_votes >= 0, 'new_votes must be non-negative'); - proposal_total_nay::InternalContractStateTrait::write( - ref state.proposal_total_nay, prop_id, new_votes.into() - ); + state.proposal_total_nay.write(prop_id, new_votes.into()); } else { - let curr_votes: u128 = proposal_total_yay::InternalContractStateTrait::read( - @state.proposal_total_yay, prop_id - ) - .try_into() - .unwrap(); + let curr_votes: u128 = state.proposal_total_yay.read(prop_id).try_into().unwrap(); let new_votes: u128 = curr_votes + caller_voting_power; assert(new_votes >= 0, 'new_votes must be non-negative'); - proposal_total_yay::InternalContractStateTrait::write( - ref state.proposal_total_yay, prop_id, new_votes.into() - ); + state.proposal_total_yay.write(prop_id, new_votes.into()); } state.emit(Governance::Voted { prop_id: prop_id, voter: caller_addr, opinion: opinion }); } @@ -329,16 +271,13 @@ mod Proposals { fn check_proposal_passed_express(prop_id: felt252) -> u8 { let state = Governance::unsafe_new_contract_state(); - let gov_token_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - let yay_tally_felt: felt252 = proposal_total_yay::InternalContractStateTrait::read( - @state.proposal_total_yay, prop_id - ); + let gov_token_addr = state.get_governance_token_address(); + let yay_tally_felt: felt252 = state.proposal_total_yay.read(prop_id); let yay_tally: u128 = yay_tally_felt.try_into().unwrap(); let total_eligible_votes_from_tokenholders_u256: u256 = IERC20Dispatcher { contract_address: gov_token_addr - }.totalSupply(); + } + .totalSupply(); assert(total_eligible_votes_from_tokenholders_u256.high == 0, 'totalSupply weirdly high'); let total_eligible_votes_from_tokenholders: u128 = total_eligible_votes_from_tokenholders_u256 @@ -363,9 +302,7 @@ mod Proposals { fn get_proposal_status(prop_id: felt252) -> felt252 { let state = Governance::unsafe_new_contract_state(); - let end_block_number_felt: felt252 = proposal_vote_ends::InternalContractStateTrait::read( - @state.proposal_vote_ends, prop_id - ); + let end_block_number_felt: felt252 = state.proposal_vote_ends.read(prop_id); let end_block_number: u64 = end_block_number_felt.try_into().unwrap(); let current_block_number: u64 = get_block_info().unbox().block_number; @@ -373,15 +310,9 @@ mod Proposals { return check_proposal_passed_express(prop_id).into(); } - let gov_token_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - let nay_tally_felt: felt252 = proposal_total_nay::InternalContractStateTrait::read( - @state.proposal_total_nay, prop_id - ); - let yay_tally_felt: felt252 = proposal_total_yay::InternalContractStateTrait::read( - @state.proposal_total_yay, prop_id - ); + let gov_token_addr = state.get_governance_token_address(); + let nay_tally_felt: felt252 = state.proposal_total_nay.read(prop_id); + let yay_tally_felt: felt252 = state.proposal_total_yay.read(prop_id); let nay_tally: u128 = nay_tally_felt.try_into().unwrap(); let yay_tally: u128 = yay_tally_felt.try_into().unwrap(); let total_tally: u128 = yay_tally + nay_tally; @@ -389,9 +320,8 @@ mod Proposals { // If QUORUM = 10, quorum was not met if (total_tally*100) < (total_eligible * 10). let total_tally_multiplied = total_tally * 100; - let total_eligible_votes_u256: u256 = IERC20Dispatcher { - contract_address: gov_token_addr - }.totalSupply(); + let total_eligible_votes_u256: u256 = IERC20Dispatcher { contract_address: gov_token_addr } + .totalSupply(); assert(total_eligible_votes_u256.high == 0, 'unable to check quorum'); let total_eligible_votes: u128 = total_eligible_votes_u256.low; @@ -410,78 +340,4 @@ mod Proposals { return constants::MINUS_ONE; // yay_tally < nay_tally } } - - - fn vote_investor(prop_id: felt252, opinion: felt252) { - // Checks - assert( - (opinion == constants::MINUS_ONE) | (opinion == 1), 'opinion must be either 1 or -1' - ); - - let mut state = Governance::unsafe_new_contract_state(); - - let caller_addr = get_caller_address(); - let investor_voting_power: u128 = investor_voting_power::InternalContractStateTrait::read( - @state.investor_voting_power, caller_addr - ) - .try_into() - .unwrap(); - assert(investor_voting_power != 0, 'caller not whitelisted investor'); - - let curr_vote_status: felt252 = proposal_voted_by::InternalContractStateTrait::read( - @state.proposal_voted_by, (prop_id, caller_addr) - ); - assert(curr_vote_status == 0, 'already voted'); - - assert_voting_in_progress(prop_id); - - // Calculate real voting power - let gov_token_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - let total_supply_u256: u256 = IERC20Dispatcher { - contract_address: gov_token_addr - }.totalSupply(); - assert(total_supply_u256.high == 0, 'totalSupply weirdly high'); - let total_supply: u128 = total_supply_u256.low; - let real_investor_voting_power: u128 = total_supply - constants::TEAM_TOKEN_BALANCE; - assert(total_supply >= constants::TEAM_TOKEN_BALANCE, 'total_supply= 0, 'new_votes negative'); - proposal_total_nay::InternalContractStateTrait::write( - ref state.proposal_total_nay, prop_id, new_votes.into() - ); - } else { - let curr_votes: u128 = proposal_total_yay::InternalContractStateTrait::read( - @state.proposal_total_yay, prop_id - ) - .try_into() - .unwrap(); - let new_votes: u128 = curr_votes + vote_power; - assert(new_votes >= 0, 'new_votes negative'); - proposal_total_yay::InternalContractStateTrait::write( - ref state.proposal_total_yay, prop_id, new_votes.into() - ); - } - } } diff --git a/src/traits.cairo b/src/traits.cairo index db51c894..4aca7aa5 100644 --- a/src/traits.cairo +++ b/src/traits.cairo @@ -96,7 +96,7 @@ trait IAMM { strike_price: Math64x61_, ) -> ContractAddress; fn get_lptokens_for_underlying( - ref self: TContractState, pooled_token_addr: ContractAddress, underlying_amt: u256, + ref self: TContractState, pooled_token_addr: ContractAddress, underlying_amt: u256, ) -> u256; fn get_underlying_for_lptokens( self: @TContractState, pooled_token_addr: ContractAddress, lpt_amt: u256 @@ -109,7 +109,7 @@ trait IAMM { fn get_option_with_position_of_user( self: @TContractState, user_address: ContractAddress ) -> Array; - fn get_all_lptoken_addresses(self: @TContractState, ) -> Array; + fn get_all_lptoken_addresses(self: @TContractState,) -> Array; fn get_value_of_pool_position( self: @TContractState, lptoken_address: ContractAddress ) -> Math64x61_; @@ -187,7 +187,7 @@ trait IAMM { self: @TContractState, lptoken_address: ContractAddress ) -> Math64x61_; fn set_pool_volatility_adjustment_speed_external( - ref self: TContractState, lptoken_address: ContractAddress, new_speed: Math64x61_, + ref self: TContractState, lptoken_address: ContractAddress, new_speed: Math64x61_, ); fn get_pool_volatility( self: @TContractState, lptoken_address: ContractAddress, maturity: felt252 @@ -222,7 +222,7 @@ trait IAMM { fn initializer(ref self: TContractState, proxy_admin: ContractAddress); fn upgrade(ref self: TContractState, new_implementation: felt252); fn setAdmin(ref self: TContractState, address: felt252); - fn getImplementationHash(self: @TContractState, ) -> felt252; + fn getImplementationHash(self: @TContractState,) -> felt252; } #[starknet::interface] diff --git a/src/upgrades.cairo b/src/upgrades.cairo index 739d5763..cccaa211 100644 --- a/src/upgrades.cairo +++ b/src/upgrades.cairo @@ -1,4 +1,6 @@ mod Upgrades { + use core::starknet::storage::StorageMemberAccessTrait; + use governance::contract::IGovernance; use traits::TryInto; use option::OptionTrait; use traits::Into; @@ -12,12 +14,19 @@ mod Upgrades { use starknet::class_hash; use governance::proposals::Proposals; use governance::contract::Governance::{ - proposal_applied, amm_address, governance_token_address, merkle_root, proposal_details + proposal_applied, amm_address, governance_token_address, proposal_details }; use governance::types::PropDetails; use governance::contract::Governance; use governance::contract::Governance::unsafe_new_contract_state; + use governance::contract::Governance::proposal_appliedContractMemberStateTrait; + use governance::contract::Governance::proposal_detailsContractMemberStateTrait; + use governance::contract::Governance::airdrop_component::UnsafeNewContractStateTraitForAirdropImpl; + use governance::contract::Governance::airdrop_component; + use governance::contract::Governance::airdrop_component::ComponentState; + use governance::contract::Governance::ContractState; + use governance::traits::IAMMDispatcher; use governance::traits::IAMMDispatcherTrait; @@ -28,14 +37,10 @@ mod Upgrades { let mut state = Governance::unsafe_new_contract_state(); let status = Proposals::get_proposal_status(prop_id); assert(status == 1, 'prop not passed'); - let applied: felt252 = proposal_applied::InternalContractStateTrait::read( - @state.proposal_applied, prop_id - ); + let applied: felt252 = state.proposal_applied.read(prop_id); assert(applied == 0, 'Proposal already applied'); - let prop_details: PropDetails = proposal_details::InternalContractStateTrait::read( - @state.proposal_details, prop_id - ); + let prop_details: PropDetails = state.proposal_details.read(prop_id); let contract_type = prop_details.to_upgrade; Proposals::assert_correct_contract_type(contract_type); @@ -46,9 +51,7 @@ mod Upgrades { // TODO use full match/switch when supported match contract_type { 0 => { - let amm_addr: ContractAddress = amm_address::InternalContractStateTrait::read( - @state.amm_address - ); + let amm_addr: ContractAddress = state.get_amm_address(); IAMMDispatcher { contract_address: amm_addr }.upgrade(impl_hash); }, _ => { @@ -56,16 +59,13 @@ mod Upgrades { let impl_hash_classhash: ClassHash = impl_hash.try_into().unwrap(); syscalls::replace_class_syscall(impl_hash_classhash); } else if (contract_type == 2) { - let govtoken_addr = governance_token_address::InternalContractStateTrait::read( - @state.governance_token_address - ); - IGovernanceTokenDispatcher { - contract_address: govtoken_addr - }.upgrade(impl_hash); + let govtoken_addr = state.get_governance_token_address(); + IGovernanceTokenDispatcher { contract_address: govtoken_addr } + .upgrade(impl_hash); } else if (contract_type == 3) { - merkle_root::InternalContractStateTrait::write( - ref state.merkle_root, impl_hash - ); + let mut airdrop_component_state: ComponentState = + Governance::airdrop_component::unsafe_new_component_state(); + airdrop_component_state.merkle_root.write(impl_hash); } else { assert( contract_type == 4, 'invalid contract_type' @@ -73,9 +73,7 @@ mod Upgrades { } } } - proposal_applied::InternalContractStateTrait::write( - ref state.proposal_applied, prop_id, 1 - ); // Mark the proposal as applied + state.proposal_applied.write(prop_id, 1); // Mark the proposal as applied // TODO emit event } }