Skip to content

Commit

Permalink
Merge pull request #167 from saimeunt/feat/refactor-current-goal-state
Browse files Browse the repository at this point in the history
Refactor current_goal_state
  • Loading branch information
EmmanuelAR authored Oct 30, 2024
2 parents ec4325d + 8c1505d commit 89b68fe
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.snfoundry_cache
target
.DS_Store
.DS_Store
5 changes: 5 additions & 0 deletions contracts/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ test = "snforge test"

[[target.starknet-contract]]
casm = true

[[tool.snforge.fork]]
name = "Mainnet"
url = "https://starknet-mainnet.public.blastapi.io/rpc/v0_7"
block_id.number = "519354"
2 changes: 2 additions & 0 deletions contracts/src/constants/funds/starknet_constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ use starknet::ContractAddress;
pub mod StarknetConstants {
pub const STRK_TOKEN_ADDRESS: felt252 =
0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d;
pub const STRK_TOKEN_MINTER_ADDRESS: felt252 =
0x0594c1582459ea03f77deaf9eb7e3917d6994a03c13405ba42867f83d85f085d;
}
47 changes: 27 additions & 20 deletions contracts/src/fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub trait IFund<TContractState> {
fn setGoal(ref self: TContractState, goal: u256);
fn getGoal(self: @TContractState) -> u256;
fn receiveDonation(ref self: TContractState, strks: u256);
fn getCurrentGoalState(self: @TContractState) -> u256;
fn get_current_goal_state(self: @TContractState) -> u256;
fn setState(ref self: TContractState, state: u8);
fn getState(self: @TContractState) -> u8;
fn getVoter(self: @TContractState) -> u32;
Expand Down Expand Up @@ -83,7 +83,6 @@ mod Fund {
up_votes: u32,
voters: LegacyMap::<ContractAddress, u32>,
goal: u256,
current_goal_state: u256,
state: u8,
}

Expand All @@ -100,7 +99,6 @@ mod Fund {
self.reason.write(" ");
self.up_votes.write(FundConstants::INITIAL_UP_VOTES);
self.goal.write(goal);
self.current_goal_state.write(FundConstants::INITIAL_GOAL);
self.state.write(FundStates::RECOLLECTING_VOTES);
}

Expand Down Expand Up @@ -171,24 +169,27 @@ mod Fund {
self.state.read() == FundStates::RECOLLECTING_DONATIONS,
'Fund not recollecting dons!'
);
self.current_goal_state.write(self.current_goal_state.read() + strks);
if self.current_goal_state.read() >= self.goal.read() {
self
.token_dispatcher()
.transfer_from(get_caller_address(), get_contract_address(), strks);
let current_balance = self.get_current_goal_state();
if current_balance >= self.goal.read() {
self.state.write(FundStates::CLOSED);
}

// Emit receiveDonation event
self
.emit(
DonationReceived {
current_balance: self.current_goal_state.read(),
current_balance,
donated_strks: strks,
donator_address: get_caller_address(),
fund_contract_address: get_contract_address(),
}
)
}
fn getCurrentGoalState(self: @ContractState) -> u256 {
return self.current_goal_state.read();
fn get_current_goal_state(self: @ContractState) -> u256 {
self.token_dispatcher().balance_of(get_contract_address())
}
fn setState(ref self: ContractState, state: u8) {
self.state.write(state);
Expand All @@ -204,27 +205,33 @@ mod Fund {
let caller = get_caller_address();
assert!(self.owner.read() == caller, "You are not the owner");
assert(self.state.read() == FundStates::CLOSED, 'Fund not close goal yet.');
assert(self.getCurrentGoalState() > 0, 'Fund hasnt reached its goal yet');
assert(self.get_current_goal_state() > 0, 'Fund hasnt reached its goal yet');
// Withdraw
let starknet_contract_address = contract_address_const::<
StarknetConstants::STRK_TOKEN_ADDRESS
>();
let starknet_dispatcher = IERC20Dispatcher {
contract_address: starknet_contract_address
};
let balance = starknet_dispatcher.balance_of(get_contract_address());
//TODO: Calculate balance to deposit in owner address and in fund manager address (95% and 5%), also transfer the amount to fund manager address.
starknet_dispatcher.transfer(self.getOwner(), balance);
assert(self.getCurrentGoalState() != 0, 'Fund hasnt reached its goal yet');
let withdrawn_amount = self.get_current_goal_state();
// TODO: Calculate balance to deposit in owner address and in fund manager address (95%
// and 5%), also transfer the amount to fund manager address.
self.token_dispatcher().transfer(self.getOwner(), withdrawn_amount);
assert(self.get_current_goal_state() != 0, 'Fund hasnt reached its goal yet');
self.setState(4);
self
.emit(
DonationWithdraw {
owner_address: self.getOwner(),
fund_contract_address: get_contract_address(),
withdrawn_amount: balance
withdrawn_amount
}
);
}
}
// *************************************************************************
// INTERNALS
// *************************************************************************
#[generate_trait]
impl InternalImpl of InternalTrait {
fn token_dispatcher(self: @ContractState) -> IERC20Dispatcher {
IERC20Dispatcher {
contract_address: contract_address_const::<StarknetConstants::STRK_TOKEN_ADDRESS>()
}
}
}
}
39 changes: 30 additions & 9 deletions contracts/tests/test_fund.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
// FUND TEST
// ***************************************************************************************
use starknet::{ContractAddress, contract_address_const};
use starknet::syscalls::call_contract_syscall;

use snforge_std::{declare, ContractClassTrait, start_cheat_caller_address_global};
use snforge_std::{
declare, ContractClassTrait, start_cheat_caller_address_global, start_cheat_caller_address,
cheat_caller_address, CheatSpan
};

use openzeppelin::utils::serde::SerializedAppend;
use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait};

use gostarkme::fund::IFundDispatcher;
use gostarkme::fund::IFundDispatcherTrait;
use gostarkme::constants::{funds::{fund_manager_constants::FundManagerConstants},};
use gostarkme::constants::{funds::{starknet_constants::StarknetConstants},};

fn ID() -> u128 {
1
Expand Down Expand Up @@ -46,6 +52,7 @@ fn _setup_() -> ContractAddress {
// TEST
// ***************************************************************************************
#[test]
#[fork("Mainnet")]
fn test_constructor() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
Expand All @@ -55,7 +62,7 @@ fn test_constructor() {
let reason = dispatcher.getReason();
let up_votes = dispatcher.getUpVotes();
let goal = dispatcher.getGoal();
let current_goal_state = dispatcher.getCurrentGoalState();
let current_goal_state = dispatcher.get_current_goal_state();
let state = dispatcher.getState();
assert(id == ID(), 'Invalid id');
assert(owner == OWNER(), 'Invalid owner');
Expand Down Expand Up @@ -131,20 +138,34 @@ fn test_receive_vote_unsuccessful_double_vote() {
}

#[test]
#[fork("Mainnet")]
fn test_receive_donation_successful() {
let contract_address = _setup_();
let dispatcher = IFundDispatcher { contract_address };
let goal: u256 = 10;
let minter_address = contract_address_const::<StarknetConstants::STRK_TOKEN_MINTER_ADDRESS>();
let token_address = contract_address_const::<StarknetConstants::STRK_TOKEN_ADDRESS>();
let token_dispatcher = IERC20Dispatcher { contract_address: token_address };
// Put state as recollecting dons
dispatcher.setState(2);
// Put 10 strks as goal, only fund manager
start_cheat_caller_address_global(FUND_MANAGER());
dispatcher.setGoal(10);
start_cheat_caller_address(contract_address, FUND_MANAGER());
dispatcher.setGoal(goal);
// fund the manager with STRK token
cheat_caller_address(token_address, minter_address, CheatSpan::TargetCalls(1));
let mut calldata = array![];
calldata.append_serde(FUND_MANAGER());
calldata.append_serde(goal);
call_contract_syscall(token_address, selector!("permissioned_mint"), calldata.span()).unwrap();
// approve
cheat_caller_address(token_address, FUND_MANAGER(), CheatSpan::TargetCalls(1));
token_dispatcher.approve(contract_address, goal);
// Donate 5 strks
dispatcher.receiveDonation(5);
let current_goal_state = dispatcher.getCurrentGoalState();
assert(current_goal_state == 5, 'Receive donation not working');
dispatcher.receiveDonation(goal / 2);
let current_goal_state = dispatcher.get_current_goal_state();
assert(current_goal_state == goal / 2, 'Receive donation not working');
// Donate 5 strks, the goal is done
dispatcher.receiveDonation(5);
dispatcher.receiveDonation(goal / 2);
let state = dispatcher.getState();
assert(state == 3, 'State should be close');
}
Expand All @@ -156,7 +177,7 @@ fn test_receive_donation_unsuccessful_wrong_state() {
let dispatcher = IFundDispatcher { contract_address };
// Put a wrong state to receive donations
dispatcher.setState(1);
// Donate
// Donate
dispatcher.receiveDonation(5);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/tests/test_fund_manager.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn _setup_() -> (ContractAddress, ClassHash) {
fund_manager_calldata.append_serde(fund_class_hash);
let (contract_address, _) = fund_manager.deploy(@fund_manager_calldata).unwrap();

return (contract_address, fund_class_hash,);
return (contract_address, fund_class_hash);
}

// ******************************************************************************
Expand Down

0 comments on commit 89b68fe

Please sign in to comment.