diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cbfff96..c216cbd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,9 @@ env: jobs: build: runs-on: ubuntu-latest + env: + MAINNET_NODE_URL: ${{ secrets.MAINNET_NODE_URL }} + SEPOLIA_NODE_URL: ${{ secrets.SEPOLIA_NODE_URL }} steps: - name: Checkout (GitHub) uses: actions/checkout@v3 diff --git a/Scarb.toml b/Scarb.toml index 4b22e4dc..20ae119d 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -23,12 +23,12 @@ sort-module-level-items = true [[tool.snforge.fork]] name = "MAINNET" -url = "http://178.32.172.148:6060/v0_7" +url = "$MAINNET_NODE_URL" block_id.tag = "Latest" [[tool.snforge.fork]] name = "SEPOLIA" -url = "http://178.32.172.148:6062/v0_7" +url = "$SEPOLIA_NODE_URL" block_id.tag = "Latest" RUST_BACKTRACE = 1 diff --git a/src/contract.cairo b/src/contract.cairo index d26c2870..cd42ed70 100644 --- a/src/contract.cairo +++ b/src/contract.cairo @@ -179,7 +179,10 @@ mod Governance { treasury_calldata.append(governance_address.into()); treasury_calldata.append(0x1); // carmine amm addr treasury_calldata.append(0x1); // zklend addr - treasury_calldata.append(0x027994c503bd8C32525FBDAf9d398bDd4e86757988C64581B055A06c5955eA49); // first guardian + treasury_calldata + .append( + 0x027994c503bd8C32525FBDAf9d398bDd4e86757988C64581B055A06c5955eA49 + ); // first guardian let (treasury_address, _) = deploy_syscall( treasury_classhash, 42, treasury_calldata.span(), false ) @@ -203,7 +206,8 @@ mod Governance { proposals.add_custom_proposal_config(add_guardian_custom_proposal_config); - let remove_guardian_custom_proposal_config: CustomProposalConfig = CustomProposalConfig { + let remove_guardian_custom_proposal_config: CustomProposalConfig = + CustomProposalConfig { target: treasury_address.into(), selector: selector!("remove_guardian"), library_call: false, @@ -229,8 +233,20 @@ mod Governance { let period = 21600; // 6 hours let increments_count = 56; let total_amount = 56000000000000000000; // 56 * 10**18 meaning 56 KONOHA tokens - vesting.add_linear_vesting_schedule(first_vest, period, increments_count, total_amount, 0x027994c503bd8C32525FBDAf9d398bDd4e86757988C64581B055A06c5955eA49.try_into().unwrap()); - vesting.add_linear_vesting_schedule(first_vest, period, increments_count, total_amount, recipient); + vesting + .add_linear_vesting_schedule( + first_vest, + period, + increments_count, + total_amount, + 0x027994c503bd8C32525FBDAf9d398bDd4e86757988C64581B055A06c5955eA49 + .try_into() + .unwrap() + ); + vesting + .add_linear_vesting_schedule( + first_vest, period, increments_count, total_amount, recipient + ); proposals .set_default_proposal_params( diff --git a/src/proposals.cairo b/src/proposals.cairo index ab9388a0..f4a942c7 100644 --- a/src/proposals.cairo +++ b/src/proposals.cairo @@ -13,6 +13,7 @@ trait IProposals { ) -> felt252; fn get_proposal_status(self: @TContractState, prop_id: felt252) -> felt252; fn get_live_proposals(self: @TContractState) -> Array; + fn get_appliable_proposals(self: @TContractState) -> Array; fn get_user_voted( self: @TContractState, user_address: ContractAddress, prop_id: felt252 ) -> VoteStatus; @@ -337,6 +338,34 @@ mod proposals { arr } + fn get_appliable_proposals(self: @ComponentState) -> Array { + let max: u32 = self.get_free_prop_id_timestamp().try_into().unwrap(); + let mut i: u32 = 0; + let mut arr = ArrayTrait::::new(); + + loop { + if i >= max { + break; + } + + let prop_id: felt252 = i.into(); + let current_status = self.get_proposal_status(prop_id); + + // is passed + if current_status == 1 { + let applied: felt252 = self.proposal_applied.read(prop_id); + + // is not applied + if applied == 0 { + arr.append(prop_id); + } + } + i += 1; + }; + + arr + } + fn get_user_voted( self: @ComponentState, user_address: ContractAddress, prop_id: felt252 ) -> VoteStatus { diff --git a/tests/deploy.cairo b/tests/deploy.cairo index ccde884d..fea09984 100644 --- a/tests/deploy.cairo +++ b/tests/deploy.cairo @@ -6,8 +6,8 @@ use snforge_std::{ //useful for debugging -#[test] -#[fork("SEPOLIA")] +//#[test] +//#[fork("SEPOLIA")] fn test_deploy() { let gov_contract = declare("Governance").expect('unable to declare governance'); let treasury_class = 0x035ef05673259eca09f55fce176a195d110bdbc6b145c08811d0e252ea8adadb; diff --git a/tests/proposals_tests.cairo b/tests/proposals_tests.cairo index 3f227db0..74538b36 100644 --- a/tests/proposals_tests.cairo +++ b/tests/proposals_tests.cairo @@ -586,3 +586,50 @@ fn test_get_comments() { assert_eq!(res_span.at(2).ipfs_hash.clone(), ipfs_hash_3); } +#[test] +fn test_get_appliable_proposals() { + let (gov, _voting, floating) = deploy_governance_and_both_tokens(); + set_staking_curve(gov.contract_address); + let gov_contract_addr = gov.contract_address; + + let dispatcher = IProposalsDispatcher { contract_address: gov_contract_addr }; + stake_all(gov.contract_address, floating, admin_addr.try_into().unwrap()); + start_prank(CheatTarget::One(gov_contract_addr), admin_addr.try_into().unwrap()); + + // create proposals 1, 2, 3 + let prop_id_1 = dispatcher.submit_proposal(123, 4); + let prop_id_2 = dispatcher.submit_proposal(124, 4); + let prop_id_3 = dispatcher.submit_proposal(125, 4); + + // vote on proposals 1, 2 + dispatcher.vote(prop_id_1, 1); + dispatcher.vote(prop_id_2, 1); + + //simulate passage of time + let current_timestamp = get_block_timestamp(); + let end_timestamp = current_timestamp + PROPOSAL_VOTING_SECONDS; + start_warp(CheatTarget::One(gov.contract_address), end_timestamp + 1); + + // 1, 2 should be passed, 3 should be expired + assert!(dispatcher.get_proposal_status(prop_id_1) == 1, "proposal 1 not passed!"); + assert!(dispatcher.get_proposal_status(prop_id_2) == 1, "proposal 2 not passed!"); + assert!( + dispatcher.get_proposal_status(prop_id_3) == constants::MINUS_ONE, "proposal 3 not expired!" + ); + + let upgrades_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr }; + + let appliable_proposals_before = dispatcher.get_appliable_proposals(); + assert!(appliable_proposals_before.len() == 2, "unexpected number of appliable proposals!"); + + // apply proposal 2 + upgrades_dispatcher.apply_passed_proposal(prop_id_2); + + // should be only proposal 1 + let mut appliable_proposals_after = dispatcher.get_appliable_proposals(); + assert!(appliable_proposals_after.len() == 1, "more than 1 appliable proposal!"); + + assert!( + appliable_proposals_after.pop_front().unwrap() == prop_id_1, "wrong appliable proposal id!" + ); +} diff --git a/tests/test_treasury.cairo b/tests/test_treasury.cairo index 5d1cca2f..855c1b3a 100644 --- a/tests/test_treasury.cairo +++ b/tests/test_treasury.cairo @@ -20,7 +20,8 @@ use openzeppelin::access::ownable::interface::{ }; use openzeppelin::upgrades::interface::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait}; use snforge_std::{ - BlockId, declare, ContractClassTrait, ContractClass, prank, CheatSpan, CheatTarget, roll, warp + BlockId, declare, get_class_hash, ContractClassTrait, ContractClass, prank, CheatSpan, + CheatTarget, roll, warp }; use starknet::{ContractAddress, get_block_number, get_block_timestamp, ClassHash}; mod testStorage { @@ -68,9 +69,19 @@ fn get_important_addresses() -> ( deployed_contract }, // FIXME – this is suboptimal, but afaik no way to get this in current snforge version? - Result::Err(_) => 0x04c990da03da72bdfb10db5c04e8aaa9d5404a07fe454037facb7744c132d42c - .try_into() - .unwrap() + Result::Err(_) => { // already declared. we should 'only' deploy //0x04c990da03da72bdfb10db5c04e8aaa9d5404a07fe454037facb7744c132d42c.try_into().unwrap() + let r = ContractClass { + class_hash: 0x035ef05673259eca09f55fce176a195d110bdbc6b145c08811d0e252ea8adadb + .try_into() + .unwrap() + }; + let contract_address = r.precalculate_address(@calldata); + prank( + CheatTarget::One(contract_address), gov_contract_address, CheatSpan::TargetCalls(1) + ); + let (deployed_contract, _) = r.deploy(@calldata).unwrap(); + deployed_contract + } }; return ( @@ -862,17 +873,18 @@ fn test_deposit_withdraw_carmine() { .try_into() .unwrap(); let sequencer_address: ContractAddress = - 0x01176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8 + 0x01176a1bd84444c89232ec27754698e5d2e7e1a7f1539f12027f28b23ec9f3d8 // 0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b .try_into() .unwrap(); // random whale - prank(CheatTarget::One(eth_addr), sequencer_address, CheatSpan::TargetCalls(1)); let transfer_dispatcher = IERC20Dispatcher { contract_address: eth_addr }; + prank(CheatTarget::One(eth_addr), sequencer_address, CheatSpan::TargetCalls(2)); let oneeth = 1000000000000000000; let to_deposit = 900000000000000000; transfer_dispatcher.transfer(treasury_contract_address, oneeth); assert( - transfer_dispatcher.balanceOf(treasury_contract_address) >= to_deposit, 'balance too low??' + transfer_dispatcher.balanceOf(treasury_contract_address) >= to_deposit, + 'balance after tx too low??' ); prank( CheatTarget::One(treasury_contract_address), gov_contract_address, CheatSpan::TargetCalls(1) @@ -893,10 +905,7 @@ fn test_deposit_withdraw_carmine() { roll( CheatTarget::All, get_block_number() + 1, CheatSpan::Indefinite ); // to bypass sandwich guard - treasury_dispatcher - .withdraw_liquidity( - eth_addr, usdc_addr, eth_addr, 0, (to_deposit - 100000000000000000).into() - ); + treasury_dispatcher.withdraw_liquidity(eth_addr, usdc_addr, eth_addr, 0, to_deposit.into()); assert( transfer_dispatcher.balanceOf(treasury_contract_address) >= to_deposit, 'balance too low??' ); @@ -912,7 +921,7 @@ fn test_deposit_withdraw_zklend() { .try_into() .unwrap(); let random_whale: ContractAddress = - 0x4267ae838da77a52384283f3321a0746557023d24cb823115d2da5c8c4f1a42 + 0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b // ekubo core .try_into() .unwrap(); let usdc_dispatcher = IERC20Dispatcher { contract_address: usdc_addr }; @@ -923,7 +932,6 @@ fn test_deposit_withdraw_zklend() { let deposit_amt = 2000000; // 2 USDC usdc_dispatcher.transfer(treasury_contract_address, deposit_amt); assert(usdc_dispatcher.balanceOf(treasury_contract_address) >= deposit_amt, 'usdc bal too low'); - // Deposit to ZKLend Market let bal_before_deposit = usdc_dispatcher.balanceOf(treasury_contract_address); prank( @@ -958,7 +966,7 @@ fn test_deposit_withdraw_nostra_lending_pool() { .try_into() .unwrap(); let random_whale: ContractAddress = - 0x4267ae838da77a52384283f3321a0746557023d24cb823115d2da5c8c4f1a42 + 0x00000005dd3d2f4429af886cd1a3b08289dbcea99a294197e9eb43b0e0325b4b // ekubo core .try_into() .unwrap(); let usdc_dispatcher = IERC20Dispatcher { contract_address: usdc_addr };