Skip to content

Commit

Permalink
Merge pull request #5 from CarmineOptions/investigate-prop-77
Browse files Browse the repository at this point in the history
Investigate prop 77
  • Loading branch information
tensojka authored Jul 22, 2024
2 parents 6a5635d + f7e0271 commit 8dce4d7
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 43 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
paths:
- '**.cairo'
- '.github/'
- 'Scarb.lock'
- 'Scarb.toml'

env:
SCARB_VERSION: 2.6.4
FOUNDRY_VERSION: 0.23.0

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout (GitHub)
uses: actions/checkout@v3
- 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
- uses: foundry-rs/setup-snfoundry@v3
with:
starknet-foundry-version: ${{ env.FOUNDRY_VERSION }}
- name: Run tests with snforge
run: snforge test
5 changes: 5 additions & 0 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ name = "MAINNET"
url = "http://178.32.172.148:6060/v0_7"
block_id.tag = "Latest"

[[tool.snforge.fork]]
name = "MAINNET_BEFORE_UPGRADE_TO_KONOHA"
url = "http://178.32.172.148:6060/v0_7"
block_id.number = "652000"

[[tool.snforge.fork]]
name = "SEPOLIA"
url = "http://178.32.172.148:6062/v0_7"
Expand Down
2 changes: 1 addition & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod carm;
pub mod constants;
pub mod contract;
mod options;
mod proposals;
pub mod proposals;
pub mod staking;
mod traits;
mod types;
Expand Down
2 changes: 1 addition & 1 deletion src/proposals.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use konoha::types::{ContractType, PropDetails, VoteStatus, CustomProposalConfig}
use starknet::ContractAddress;

#[starknet::interface]
trait IProposals<TContractState> {
pub trait IProposals<TContractState> {
fn vote(ref self: TContractState, prop_id: felt252, opinion: felt252);
fn get_proposal_details(self: @TContractState, prop_id: felt252) -> PropDetails;
fn get_vote_counts(self: @TContractState, prop_id: felt252) -> (u128, u128);
Expand Down
4 changes: 2 additions & 2 deletions tests/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod unstake_airdrop;
mod test_prop_pass;
//mod unstake_airdrop;
//mod add_options;
mod upgrade;
pub mod utils;

190 changes: 190 additions & 0 deletions tests/test_prop_pass.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use amm_governance::proposals::{IProposalsDispatcherTrait, IProposalsDispatcher};
use amm_governance::staking::{IStakingDispatcherTrait, IStakingDispatcher};
use openzeppelin::token::erc20::interface::{IERC20DispatcherTrait, IERC20Dispatcher};

use snforge_std::{CheatSpan, CheatTarget, prank, start_warp};
use starknet::{ContractAddress, get_block_timestamp};

const DECS: u128 = 1000000000000000000; // 10*18

fn get_team_addresses() -> @Span<felt252> {
let arr = array![
0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1,
0x06717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af,
0x058d2ddce3e4387dc0da7e45c291cb436bb809e00a4c132bcc5758e4574f55c7,
0x05e61dfb8a9863e446981e804a203a7ad3a2d15495c85b79cfd053ec63e9bfb3,
0x04379c63976feaca8019db2c08f7af8e976b11aef7eda9dfe2ef604e76fc99d2,
0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233,
0x00d79a15d84f5820310db21f953a0fae92c95e25d93cb983cc0c27fc4c52273c,
0x03d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad,
0x06fd0529AC6d4515dA8E5f7B093e29ac0A546a42FB36C695c8f9D13c5f787f82,
0x04d2FE1Ff7c0181a4F473dCd982402D456385BAE3a0fc38C49C0A99A620d1abe,
0x062c290f0afa1ea2d6b6d11f6f8ffb8e626f796e13be1cf09b84b2edaa083472,
0x01714ab9a05b062e0c09cf635fd469ce664c914ef9d9ff2394928e31707ce9a6,
0x06c59d2244250f2540a2694472e3c31262e887ff02582ef864bf0e76c34e1298,
0x0528f064c43e2d6Ee73bCbfB725bAa293CD31Ea1f1861EA2F80Bc283Ea4Ad728,
0x05105649f42252f79109356e1c8765b7dcdb9bf4a6a68534e7fc962421c7efd2,
0x00777558f1c767126461540d1f10118981d30bd620707e99686bfc9f00ae66f0,
0x06e2c2a5da2e5478b1103d452486afba8378e91f32a124f0712f09edd3ccd923,
0x035e0845154423c485e5216f70496130079b5ddc8ac66e3e316184482788e2a0,
0x0244dda2c6581eb158db225992153c9d49e92c412424daeb83a773fa9822eeef, // team multisig
0x059c0d4c5dde72e8cab06105be5f2beeb4de52dc516ccbafcaa0b58894d16397, // company wallet
];
@arr.span()
}

fn get_investor_addresses() -> @Span<felt252> {
let arr = array![
0x05a4523982b437aadd1b5109b6618c46f7b1c42f5f9e7de1a3b84091f87d411b,
0x056d761e1e5d1918dba05de02afdbd8de8da01a63147dce828c9b1fe9227077d, // investor multisig
];
@arr.span()
}

fn get_adjusted_group_voting_power(contract: IStakingDispatcher, investors: bool) -> u128 {
let mut total: u128 = 0;
let mut addresses = *get_team_addresses();
loop {
match addresses.pop_front() {
Option::Some(addr) => {
total += contract.get_adjusted_voting_power((*addr).try_into().unwrap());
},
Option::None(_) => { break total; }
}
}
}


fn get_total_group_voting_power(contract: IStakingDispatcher, investors: bool) -> u128 {
let mut total: u128 = 0;
let mut addresses = if investors {
*get_investor_addresses()
} else {
*get_team_addresses()
};
loop {
match addresses.pop_front() {
Option::Some(addr) => {
total += contract.get_total_voting_power((*addr).try_into().unwrap());
},
Option::None(_) => { break total; }
}
}
}

fn get_total_voted_adjusted(
proposals: IProposalsDispatcher, staking: IStakingDispatcher, prop_id: u32
) -> u128 {
let mut addresses = *get_team_addresses();
let mut total = 0;
loop {
match addresses.pop_front() {
Option::Some(addr) => {
if (proposals.get_user_voted((*addr).try_into().unwrap(), prop_id.into()) != 0) {
total += staking.get_adjusted_voting_power((*addr).try_into().unwrap());
}
},
Option::None(_) => { break total; }
}
}
}

#[test]
#[fork("MAINNET")]
fn test_prop_pass() {
let staking = IStakingDispatcher {
contract_address: 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f
.try_into()
.unwrap()
};
let total_team_adj = get_adjusted_group_voting_power(staking, false);
println!("total team adjusted: {:?}", total_team_adj / DECS);
let total_team_total = get_total_group_voting_power(staking, false);
println!("total team total: {:?}", total_team_total / DECS);
let investors_total = get_total_group_voting_power(staking, true);
println!("investors total: {:?}", investors_total);
let vecrm = IERC20Dispatcher {
contract_address: 0x3c0286e9e428a130ae7fbbe911b794e8a829c367dd788e7cfe3efb0367548fa
.try_into()
.unwrap()
};
println!("vecrm total supply: {:?}", vecrm.total_supply() / DECS.into());
let props = IProposalsDispatcher {
contract_address: 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f
.try_into()
.unwrap()
};
let total_voted_on_prop_adj = get_total_voted_adjusted(props, staking, 77);
println!("total adjusted votes on prop: {:?}", total_voted_on_prop_adj / DECS);
let (yay, _nay) = props.get_vote_counts(77);
println!("recorded vote count: {:?}", yay / DECS);
}

#[test]
#[fork("MAINNET")]
fn test_can_pass_next_prop() {
let user1: ContractAddress =
0x0011d341c6e841426448ff39aa443a6dbb428914e05ba2259463c18308b86233 // team m 1
.try_into()
.unwrap();
let gov_addr = 0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f
.try_into()
.unwrap();
let props = IProposalsDispatcher { contract_address: gov_addr };
let staking = IStakingDispatcher { contract_address: gov_addr };
let vecrm = IERC20Dispatcher {
contract_address: 0x3c0286e9e428a130ae7fbbe911b794e8a829c367dd788e7cfe3efb0367548fa
.try_into()
.unwrap()
};
prank(CheatTarget::One(gov_addr), user1, CheatSpan::TargetCalls(1));
let prop_id = props.submit_proposal(0x42, 0x4);
prank(CheatTarget::One(gov_addr), user1, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);

let user2: ContractAddress = 0x0583a9d956d65628f806386ab5b12dccd74236a3c6b930ded9cf3c54efc722a1
.try_into()
.unwrap(); // team o
prank(CheatTarget::One(gov_addr), user2, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);

let user3: ContractAddress = 0x03d1525605db970fa1724693404f5f64cba8af82ec4aab514e6ebd3dec4838ad
.try_into()
.unwrap(); //team d
prank(CheatTarget::One(gov_addr), user3, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);

let user4: ContractAddress = 0x00d79a15d84f5820310db21f953a0fae92c95e25d93cb983cc0c27fc4c52273c
.try_into()
.unwrap(); //team m 2
prank(CheatTarget::One(gov_addr), user4, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);

let community1: ContractAddress =
0x0428c240649b76353644faF011B0d212e167f148fdd7479008Aa44eEaC782BfC
.try_into()
.unwrap(); // community m 1
prank(CheatTarget::One(gov_addr), community1, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);
let community1_balance: u128 = vecrm.balance_of(community1).try_into().unwrap();

let user5: ContractAddress = 0x06717eaf502baac2b6b2c6ee3ac39b34a52e726a73905ed586e757158270a0af
.try_into()
.unwrap(); //team a 1
prank(CheatTarget::One(gov_addr), user5, CheatSpan::TargetCalls(1));
props.vote(prop_id, 1);

let (yay, _nay) = props.get_vote_counts(prop_id);
assert(
get_total_voted_adjusted(props, staking, prop_id.try_into().unwrap())
+ community1_balance == yay,
'votes dont match??'
);
println!("voted on prop_id: {:?}", yay / DECS);

let curr_timestamp = get_block_timestamp();
let warped_timestamp = curr_timestamp + consteval_int!(60 * 60 * 24 * 7) + 420;

start_warp(CheatTarget::One(gov_addr), warped_timestamp);
assert(props.get_proposal_status(prop_id) == 1, 'prop not passed');
}
9 changes: 6 additions & 3 deletions tests/unstake_airdrop.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ fn test_unstake_airdrop() {
props.vote(prop_id_gov_upgrade, 1);

// Upgrade veCarm token
let prop_id_vecarm_upgrade = props.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
let prop_id_vecarm_upgrade = props
.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
props.vote(prop_id_vecarm_upgrade, 1);

// Propose Airdrop
Expand Down Expand Up @@ -230,7 +231,8 @@ fn test_unstake_airdrop_unstake_again_failing() {
props.vote(prop_id_gov_upgrade, 1);

// Upgrade veCarm token
let prop_id_vecarm_upgrade = props.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
let prop_id_vecarm_upgrade = props
.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
props.vote(prop_id_vecarm_upgrade, 1);

// Propose Airdrop
Expand Down Expand Up @@ -332,7 +334,8 @@ fn test_unstake_airdrop_team_member_failing() {
props.vote(prop_id_gov_upgrade, 1);

// Upgrade veCarm token
let prop_id_vecarm_upgrade = props.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
let prop_id_vecarm_upgrade = props
.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
props.vote(prop_id_vecarm_upgrade, 1);

// Propose Airdrop
Expand Down
40 changes: 19 additions & 21 deletions tests/upgrade.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use amm_governance::contract::{
use amm_governance::staking::{IStakingDispatcher, IStakingDispatcherTrait};
use amm_governance::vecarm::{IVeCRMDispatcher, IVeCRMDispatcherTrait};
use core::num::traits::Zero;
use konoha::constants;

use konoha::contract::IGovernanceDispatcher;
use konoha::contract::IGovernanceDispatcherTrait;
Expand All @@ -17,15 +18,15 @@ use konoha::upgrades::IUpgradesDispatcher;
use konoha::upgrades::IUpgradesDispatcherTrait;
use openzeppelin::upgrades::interface::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait};
use snforge_std::{
BlockId, declare, ContractClassTrait, ContractClass, start_prank, CheatTarget, prank, CheatSpan,
roll, start_warp
BlockId, declare, ContractClassTrait, ContractClass, start_prank, stop_prank, CheatTarget,
prank, CheatSpan, roll, start_warp
};
use starknet::{ClassHash, ContractAddress, get_block_timestamp, get_block_number};
use super::utils::vote_on_proposal;

// commented out as it fails with 'No voting power' for now
//#[test]
//#[fork("MAINNET")]

#[test]
#[fork("MAINNET")]
fn test_upgrade_to_master() {
let gov_contract_addr: ContractAddress =
0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f
Expand All @@ -37,24 +38,21 @@ fn test_upgrade_to_master() {
let gov_class: ContractClass = declare("Governance").expect('unable to declare!');
assert(Zero::is_non_zero(@gov_class.class_hash), 'new classhash zero??');
let user2_address: ContractAddress =
0x052df7acdfd3174241fa6bd5e1b7192cd133f8fc30a2a6ed99b0ddbfb5b22dcd
0x06e2c2a5da2e5478b1103d452486afba8378e91f32a124f0712f09edd3ccd923
.try_into()
.unwrap();
start_prank(CheatTarget::One(gov_contract_addr), user2_address);
prank(CheatTarget::One(gov_contract_addr), user2_address, CheatSpan::TargetCalls(1));
let new_prop_id = dispatcher.submit_proposal(gov_class.class_hash.into(), 1);
println!("Prop submitted: {:?}", new_prop_id);
vote_on_proposal(gov_contract_addr, new_prop_id.try_into().unwrap());

//simulate passage of time
let current_timestamp = get_block_timestamp();
let end_timestamp = current_timestamp + constants::PROPOSAL_VOTING_SECONDS;
start_warp(CheatTarget::One(gov_contract_addr), end_timestamp + 1);

let upgrade_dispatcher = IUpgradesDispatcher { contract_address: gov_contract_addr };
upgrade_dispatcher.apply_passed_proposal(new_prop_id);
let amm_governance = IMigrateDispatcher { contract_address: gov_contract_addr };
amm_governance.add_custom_proposals();
println!("Checking if new gov is healthy...");
assert(check_if_healthy(gov_contract_addr), 'new gov not healthy');
upgrade_amm(
gov_contract_addr,
0x0239b6f9eeb5ffba1df4da7f33e116d3603d724283bc01338125eed82964e729.try_into().unwrap()
);
}

fn test_deposit_to_amm_from_treasury(gov_contract_addr: ContractAddress) {
Expand Down Expand Up @@ -139,7 +137,7 @@ fn test_upgrade_amm_back(amm: ContractAddress, owner: ContractAddress, new_class


#[test]
#[fork("MAINNET")]
#[fork("MAINNET_BEFORE_UPGRADE_TO_KONOHA")]
fn scenario_airdrop_staked_carm() {
let gov_addr: ContractAddress =
0x001405ab78ab6ec90fba09e6116f373cda53b0ba557789a4578d8c1ec374ba0f
Expand Down Expand Up @@ -185,14 +183,14 @@ fn scenario_airdrop_staked_carm() {

let props = IProposalsDispatcher { contract_address: gov_addr };
prank(CheatTarget::One(gov_addr), user1, CheatSpan::TargetCalls(6));
let prop_id_gov_upgrade = props.submit_proposal(0x04bc8bc7c476c4fca95624809dab1f1aa718edb566184a9d6dfe54f65b32b507, 1);
let prop_id_vecarm_upgrade = props.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
let prop_id_gov_upgrade = props
.submit_proposal(0x04bc8bc7c476c4fca95624809dab1f1aa718edb566184a9d6dfe54f65b32b507, 1);
let prop_id_vecarm_upgrade = props
.submit_proposal(0x008e98fd1f76f0d6fca8b03292e1dd6c8a6c5362f5aa0fd1186592168e9ad692, 2);
props.vote(prop_id_gov_upgrade, 1);
props.vote(prop_id_vecarm_upgrade, 1);
let prop_id_airdrop = props
.submit_proposal(
0x1337, 3
); // simulate airdrop proposal, no merkle tree root yet
.submit_proposal(0x1337, 3); // simulate airdrop proposal, no merkle tree root yet
props.vote(prop_id_airdrop, 1);
prank(CheatTarget::One(gov_addr), user2, CheatSpan::TargetCalls(3));
props.vote(prop_id_gov_upgrade, 1);
Expand Down
Loading

0 comments on commit 8dce4d7

Please sign in to comment.