diff --git a/src/base/errors.cairo b/src/base/errors.cairo index 139051f..2a62486 100644 --- a/src/base/errors.cairo +++ b/src/base/errors.cairo @@ -133,6 +133,9 @@ pub mod Errors { // Throw Error when Insufficient balance pub const INSUFFICIENT_BALANCE: felt252 = 'Error: Insufficient balance'; + // Throw Error when donation token is invalid + pub const INVALID_DONATION_TOKEN: felt252 = 'Error: Invalid donation token'; + // Throw Error when Fee percent exceeds 100% pub const PROTOCOL_FEE_PERCENTAGE_EXCEED: felt252 = 'Error: Fee percent exceeds 100%'; } diff --git a/src/campaign_donation.cairo b/src/campaign_donation.cairo index c516e55..c72ab67 100644 --- a/src/campaign_donation.cairo +++ b/src/campaign_donation.cairo @@ -21,8 +21,8 @@ pub mod CampaignDonation { CALLER_NOT_CAMPAIGN_OWNER, CALLER_NOT_DONOR, CAMPAIGN_CLOSED, CAMPAIGN_HAS_DONATIONS, CAMPAIGN_NOT_CANCELLED, CAMPAIGN_NOT_CLOSED, CAMPAIGN_NOT_FOUND, CAMPAIGN_REF_EMPTY, CAMPAIGN_REF_EXISTS, CAMPAIGN_WITHDRAWN, CANNOT_DENOTE_ZERO_AMOUNT, DONATION_NOT_FOUND, - DOUBLE_WITHDRAWAL, INSUFFICIENT_ALLOWANCE, INSUFFICIENT_BALANCE, MORE_THAN_TARGET, - NFT_NOT_CONFIGURED, OPERATION_OVERFLOW, PROTOCOL_FEE_ADDRESS_NOT_SET, + DOUBLE_WITHDRAWAL, INSUFFICIENT_ALLOWANCE, INSUFFICIENT_BALANCE, INVALID_DONATION_TOKEN, + MORE_THAN_TARGET, NFT_NOT_CONFIGURED, OPERATION_OVERFLOW, PROTOCOL_FEE_ADDRESS_NOT_SET, PROTOCOL_FEE_PERCENTAGE_EXCEED, REFUND_ALREADY_CLAIMED, TARGET_NOT_REACHED, TARGET_REACHED, WITHDRAWAL_FAILED, ZERO_ALLOWANCE, ZERO_AMOUNT, }; @@ -164,13 +164,17 @@ pub mod CampaignDonation { #[abi(embed_v0)] impl CampaignDonationImpl of ICampaignDonation { fn create_campaign( - ref self: ContractState, campaign_ref: felt252, target_amount: u256, + ref self: ContractState, + campaign_ref: felt252, + target_amount: u256, + donation_token: ContractAddress, ) -> u256 { let caller = get_caller_address(); let timestamp = get_block_timestamp(); let ref_campaign = campaign_ref.clone(); let campaign_target_amount = target_amount.clone(); - let campaign_id = self._create_campaign(ref_campaign, campaign_target_amount); + let campaign_id = self + ._create_campaign(ref_campaign, campaign_target_amount, donation_token); self .emit( Event::Campaign( @@ -463,11 +467,15 @@ pub mod CampaignDonation { #[generate_trait] impl InternalImpl of InternalTrait { fn _create_campaign( - ref self: ContractState, campaign_ref: felt252, target_amount: u256, + ref self: ContractState, + campaign_ref: felt252, + target_amount: u256, + donation_token: ContractAddress, ) -> u256 { assert(campaign_ref != '', CAMPAIGN_REF_EMPTY); assert(!self.campaign_refs.read(campaign_ref), CAMPAIGN_REF_EXISTS); assert(target_amount > 0, ZERO_AMOUNT); + assert(!donation_token.is_zero(), INVALID_DONATION_TOKEN); let campaign_id: u256 = self.campaign_counts.read() + 1; let caller = get_caller_address(); let current_balance: u256 = 0; @@ -481,7 +489,7 @@ pub mod CampaignDonation { campaign_reference: campaign_ref, is_closed: false, is_goal_reached: false, - donation_token: self.donation_token.read(), + donation_token: donation_token, is_cancelled: false, }; @@ -497,7 +505,7 @@ pub mod CampaignDonation { let mut campaign = self.get_campaign(campaign_id); let contract_address = get_contract_address(); - let donation_token = self.donation_token.read(); + let donation_token = campaign.donation_token; // cannot send more than target amount assert!(amount <= campaign.target_amount, "More than Target"); @@ -560,7 +568,7 @@ pub mod CampaignDonation { assert(!self.campaign_withdrawn.read(campaign_id), DOUBLE_WITHDRAWAL); - let donation_token = self.donation_token.read(); + let donation_token = campaign.donation_token; let token_dispatcher = IERC20Dispatcher { contract_address: donation_token }; diff --git a/src/interfaces/ICampaignDonation.cairo b/src/interfaces/ICampaignDonation.cairo index 4d2c607..6a293b6 100644 --- a/src/interfaces/ICampaignDonation.cairo +++ b/src/interfaces/ICampaignDonation.cairo @@ -17,6 +17,7 @@ pub trait ICampaignDonation { /// # Arguments /// * `campaign_ref` - A unique 5-character identifier for the campaign /// * `target_amount` - The fundraising goal amount in the donation token + /// * `donation_token` - The address of the donation token /// /// # Returns /// * `u256` - The newly created campaign's ID @@ -26,7 +27,10 @@ pub trait ICampaignDonation { /// * If `campaign_ref` already exists /// * If `target_amount` is zero fn create_campaign( - ref self: TContractState, campaign_ref: felt252, target_amount: u256, + ref self: TContractState, + campaign_ref: felt252, + target_amount: u256, + donation_token: ContractAddress, ) -> u256; /// Makes a donation to a specific campaign diff --git a/src/payment_stream.cairo b/src/payment_stream.cairo index 185d10d..714592b 100644 --- a/src/payment_stream.cairo +++ b/src/payment_stream.cairo @@ -22,9 +22,9 @@ pub mod PaymentStream { use crate::base::errors::Errors::{ DECIMALS_TOO_HIGH, FEE_TOO_HIGH, INSUFFICIENT_ALLOWANCE, INSUFFICIENT_AMOUNT, INVALID_RECIPIENT, INVALID_TOKEN, NON_TRANSFERABLE_STREAM, ONLY_NFT_OWNER_CAN_DELEGATE, - SAME_COLLECTOR_ADDRESS, SAME_OWNER, STREAM_CANCELED, STREAM_HAS_DELEGATE, STREAM_NOT_ACTIVE, - STREAM_NOT_PAUSED, TOO_SHORT_DURATION, UNEXISTING_STREAM, WRONG_RECIPIENT, - WRONG_RECIPIENT_OR_DELEGATE, WRONG_SENDER, ZERO_AMOUNT, OVERDEPOSIT + OVERDEPOSIT, SAME_COLLECTOR_ADDRESS, SAME_OWNER, STREAM_CANCELED, STREAM_HAS_DELEGATE, + STREAM_NOT_ACTIVE, STREAM_NOT_PAUSED, TOO_SHORT_DURATION, UNEXISTING_STREAM, + WRONG_RECIPIENT, WRONG_RECIPIENT_OR_DELEGATE, WRONG_SENDER, ZERO_AMOUNT, }; use crate::base::types::{ProtocolMetrics, Stream, StreamMetrics, StreamStatus}; @@ -353,7 +353,6 @@ pub mod PaymentStream { // Check: stream is not canceled assert(stream.status != StreamStatus::Canceled, STREAM_CANCELED); - let token_address = stream.token; // Effect: update the stream balance by adding the deposit amount @@ -464,7 +463,7 @@ pub mod PaymentStream { } else { // For active streams, the withdrawable amount is the minimum of stream balance and // total debt - total_debt - stream.withdrawn_amount + total_debt - stream.withdrawn_amount } } @@ -673,7 +672,6 @@ pub mod PaymentStream { #[abi(embed_v0)] impl PaymentStreamImpl of IPaymentStream { - /// @notice Creates a new stream and funds it with tokens in a single transaction /// @dev Combines the create_stream and deposit functions into one efficient operation fn create_stream( @@ -806,7 +804,10 @@ pub mod PaymentStream { self.accesscontrol.revoke_role(PROTOCOL_OWNER_ROLE, current_owner); self.accesscontrol._grant_role(PROTOCOL_OWNER_ROLE, new_protocol_owner); - self.emit(ProtocolOwnerUpdated { new_protocol_owner, old_protocol_owner: current_owner }); + self + .emit( + ProtocolOwnerUpdated { new_protocol_owner, old_protocol_owner: current_owner }, + ); } fn get_fee_collector(self: @ContractState) -> ContractAddress { @@ -911,7 +912,7 @@ pub mod PaymentStream { // Pay the recipient the remaining balance let recipient = stream.recipient; - + // Update Stream in State self.streams.write(stream_id, stream); let amount_due = self._withdrawable_amount(stream_id); diff --git a/tests/test_campaign_donation.cairo b/tests/test_campaign_donation.cairo index e4ef5a9..5b1e9ba 100644 --- a/tests/test_campaign_donation.cairo +++ b/tests/test_campaign_donation.cairo @@ -68,13 +68,15 @@ fn deploy_donation_nft( #[test] fn test_successful_create_campaign() { - let (_token_address, _sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, _sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; let campaign_ref = 'Test'; let owner = contract_address_const::<'owner'>(); + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, owner); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // This is the first Campaign Created, so it will be 1. assert!(campaign_id == 1_u256, "Campaign creation failed"); @@ -93,15 +95,31 @@ fn test_successful_create_campaign() { #[test] #[should_panic(expected: 'Error: Amount must be > 0.')] fn test_create_campaign_invalid_zero_amount() { - let (_token_address, _sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, _sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 0_u256; let campaign_ref = 'Test'; + let donation_token = token_address; let owner = contract_address_const::<'owner'>(); start_cheat_caller_address(campaign_donation.contract_address, owner); - campaign_donation.create_campaign(campaign_ref, target_amount); + campaign_donation.create_campaign(campaign_ref, target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); } + +#[test] +#[should_panic(expected: 'Error: Invalid donation token')] +fn test_create_campaign_invalid_donation_token() { + let (token_address, _sender, campaign_donation, _erc721, _, _) = setup(); + let target_amount = 10_u256; + let campaign_ref = 'Test'; + let donation_token: ContractAddress = 0.try_into().unwrap(); + let owner = contract_address_const::<'owner'>(); + start_cheat_caller_address(campaign_donation.contract_address, owner); + campaign_donation.create_campaign(campaign_ref, target_amount, donation_token); + stop_cheat_caller_address(campaign_donation.contract_address); +} + + // // #[test] // // #[should_panic(expected: 'Error: Campaign Ref Exists')] // // fn test_create_campaign_duplicate_campaign_refs() { @@ -130,14 +148,17 @@ fn test_create_campaign_invalid_zero_amount() { // // } // // DONE + #[test] fn test_successful_campaign_donation() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 5000_u256; let campaign_ref = 'Test'; + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -189,9 +210,11 @@ fn test_successful_campaign_donation_twice() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; let campaign_ref = 'Test'; + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -233,9 +256,11 @@ fn test_successful_multiple_users_donating_to_a_campaign() { let target_amount = 10000_u256; let campaign_ref = 'Test'; let another_user: ContractAddress = contract_address_const::<'another_user'>(); + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -279,14 +304,32 @@ fn test_successful_multiple_users_donating_to_a_campaign() { assert(other_user_balance_after == other_user_balance_before - 300, ' USR transfer failed'); } + +#[test] +#[should_panic(expected: 'Error: Invalid donation token')] +fn test_campaign_creation_should_panic_with_invalid_token() { + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let target_amount = 10000_u256; + let campaign_ref = 'Test'; + let donation_token = contract_address_const::<0>(); + println!("donation token: {:?}", donation_token); + + start_cheat_caller_address(campaign_donation.contract_address, sender); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); +} + + #[test] fn test_target_met_successful() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; let campaign_ref = 'Test'; + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -318,12 +361,18 @@ fn test_get_campaigns() { let target_amount_1 = 1000_u256; let target_amount_2 = 2000_u256; let target_amount_3 = 3000_u256; + let donation_token_1 = contract_address_const::<'donation_token_1'>(); + let donation_token_2 = contract_address_const::<'donation_token_2'>(); + let donation_token_3 = contract_address_const::<'donation_token_3'>(); // Create multiple campaigns with different references start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id_1 = campaign_donation.create_campaign('Ref1', target_amount_1); - let campaign_id_2 = campaign_donation.create_campaign('Ref2', target_amount_2); - let campaign_id_3 = campaign_donation.create_campaign('Ref3', target_amount_3); + let campaign_id_1 = campaign_donation + .create_campaign('Ref1', target_amount_1, donation_token_1); + let campaign_id_2 = campaign_donation + .create_campaign('Ref2', target_amount_2, donation_token_2); + let campaign_id_3 = campaign_donation + .create_campaign('Ref3', target_amount_3, donation_token_3); stop_cheat_caller_address(campaign_donation.contract_address); // Get all campaigns @@ -359,10 +408,12 @@ fn test_get_campaign_donations() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let another_user: ContractAddress = contract_address_const::<'another_user'>(); let target_amount = 5000_u256; + let donation_token = token_address; // Create a campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('TestCampaign', target_amount); + let campaign_id = campaign_donation + .create_campaign('TestCampaign', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -420,12 +471,14 @@ fn test_get_campaign_donations() { #[test] fn test_get_campaign_donations_empty() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; + let donation_token = token_address; // Create a campaign but don't make any donations start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('EmptyCampaign', target_amount); + let campaign_id = campaign_donation + .create_campaign('EmptyCampaign', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Get donations for the campaign @@ -439,11 +492,14 @@ fn test_get_campaign_donations_empty() { fn test_multiple_campaigns_with_donations() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; + let donation_token = token_address; // Create multiple campaigns start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id_1 = campaign_donation.create_campaign('Campaign1', target_amount); - let campaign_id_2 = campaign_donation.create_campaign('Campaign2', target_amount); + let campaign_id_1 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); + let campaign_id_2 = campaign_donation + .create_campaign('Campaign2', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -483,9 +539,11 @@ fn test_withdraw_funds_from_campaign_successful() { let target_amount = 800_u256; let campaign_ref = 'Test'; let owner = contract_address_const::<'owner'>(); + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, owner); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; stop_cheat_caller_address(campaign_donation.contract_address); @@ -537,13 +595,15 @@ fn test_withdraw_funds_from_campaign_successful() { #[test] fn test_update_campaign_target_successful() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let target_amount = 1000_u256; let new_target = 2000_u256; + let donation_token = token_address; // Create campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', target_amount); + let campaign_id = campaign_donation.create_campaign('Test', target_amount, donation_token); // Update target campaign_donation.update_campaign_target(campaign_id, new_target); @@ -566,12 +626,14 @@ fn test_update_campaign_target_nonexistent() { #[test] #[should_panic(expected: 'Caller is Not Campaign Owner')] fn test_update_campaign_target_not_owner() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let other_user: ContractAddress = contract_address_const::<'other_user'>(); + let donation_token = token_address; // Create campaign as sender start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', 1000); + let campaign_id = campaign_donation.create_campaign('Test', 1000, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Try to update as other user @@ -585,10 +647,11 @@ fn test_update_campaign_target_not_owner() { fn test_update_campaign_target_with_donations() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; + let donation_token = token_address; // Create campaign and make donation start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', target_amount); + let campaign_id = campaign_donation.create_campaign('Test', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve and donate @@ -610,11 +673,12 @@ fn test_update_campaign_target_with_donations() { #[test] fn test_cancel_campaign_successful() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let donation_token = token_address; // Create campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', 1000); + let campaign_id = campaign_donation.create_campaign('Test', 1000, donation_token); // Cancel campaign campaign_donation.cancel_campaign(campaign_id); @@ -629,11 +693,12 @@ fn test_cancel_campaign_successful() { #[test] #[should_panic(expected: 'Error: Campaign closed')] fn test_cancel_campaign_already_closed() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let donation_token = token_address; // Create and cancel campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', 1000); + let campaign_id = campaign_donation.create_campaign('Test', 1000, donation_token); campaign_donation.cancel_campaign(campaign_id); // Try to cancel again @@ -645,10 +710,10 @@ fn test_cancel_campaign_already_closed() { fn test_claim_refund_successful() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; - + let donation_token = token_address; // Create campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', target_amount); + let campaign_id = campaign_donation.create_campaign('Test', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Make donation @@ -680,10 +745,10 @@ fn test_claim_refund_successful() { #[should_panic(expected: 'Error: Refund already claimed')] fn test_claim_refund_twice() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); - + let donation_token = token_address; // Create campaign and make donation start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', 1000); + let campaign_id = campaign_donation.create_campaign('Test', 1000, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); let token_dispatcher = IERC20Dispatcher { contract_address: token_address }; @@ -707,12 +772,12 @@ fn test_claim_refund_twice() { #[test] #[should_panic(expected: 'Error: Donation not found')] fn test_claim_refund_no_donation() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let other_user: ContractAddress = contract_address_const::<'other_user'>(); - + let donation_token = token_address; // Create campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', 1000); + let campaign_id = campaign_donation.create_campaign('Test', 1000, donation_token); // Cancel campaign campaign_donation.cancel_campaign(campaign_id); @@ -726,7 +791,7 @@ fn test_claim_refund_no_donation() { #[test] fn test_mint_donation_receipt_successful() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); // Deploy the Donation NFT contract let (erc721, donation_nft_dispatcher) = deploy_donation_nft(campaign_donation.contract_address); // Use the protocol owner to set the donation NFT address @@ -739,15 +804,16 @@ fn test_mint_donation_receipt_successful() { let target_amount = 1000_u256; let campaign_ref = 'Test'; let owner = contract_address_const::<'owner'>(); - + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, owner); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); // Simulate delegate's approval: - start_cheat_caller_address(_token_address, sender); - IERC20Dispatcher { contract_address: _token_address } + start_cheat_caller_address(token_address, sender); + IERC20Dispatcher { contract_address: token_address } .approve(campaign_donation.contract_address, 1000); - stop_cheat_caller_address(_token_address); + stop_cheat_caller_address(token_address); start_cheat_caller_address(campaign_donation.contract_address, sender); let donation_id = campaign_donation.donate_to_campaign(campaign_id, 500); @@ -796,7 +862,7 @@ fn test_mint_donation_receipt_successful() { #[test] #[should_panic(expected: 'Error: Caller is not the donor')] fn test_mint_donation_receipt_fail_if_not_donor() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); // Deploy the Donation NFT contract let (_erc721, donation_nft_dispatcher) = deploy_donation_nft( campaign_donation.contract_address, @@ -809,15 +875,16 @@ fn test_mint_donation_receipt_fail_if_not_donor() { let target_amount = 1000_u256; let campaign_ref = 'Test'; let owner = contract_address_const::<'owner'>(); - + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, owner); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); // Simulate delegate's approval: - start_cheat_caller_address(_token_address, sender); - IERC20Dispatcher { contract_address: _token_address } + start_cheat_caller_address(token_address, sender); + IERC20Dispatcher { contract_address: token_address } .approve(campaign_donation.contract_address, 1000); - stop_cheat_caller_address(_token_address); + stop_cheat_caller_address(token_address); start_cheat_caller_address(campaign_donation.contract_address, sender); let donation_id = campaign_donation.donate_to_campaign(campaign_id, 500); @@ -832,7 +899,7 @@ fn test_mint_donation_receipt_fail_if_not_donor() { #[test] #[should_panic(expected: 'NFT already minted')] fn test_mint_donation_receipt_fail_if_already_minted() { - let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); // Deploy the Donation NFT contract let (_erc721, donation_nft_dispatcher) = deploy_donation_nft( campaign_donation.contract_address, @@ -847,15 +914,16 @@ fn test_mint_donation_receipt_fail_if_already_minted() { let target_amount = 1000_u256; let campaign_ref = 'Test'; let owner = contract_address_const::<'owner'>(); - + let donation_token = token_address; start_cheat_caller_address(campaign_donation.contract_address, owner); - let campaign_id = campaign_donation.create_campaign(campaign_ref, target_amount); + let campaign_id = campaign_donation + .create_campaign(campaign_ref, target_amount, donation_token); // Simulate delegate's approval: - start_cheat_caller_address(_token_address, sender); - IERC20Dispatcher { contract_address: _token_address } + start_cheat_caller_address(token_address, sender); + IERC20Dispatcher { contract_address: token_address } .approve(campaign_donation.contract_address, 1000); - stop_cheat_caller_address(_token_address); + stop_cheat_caller_address(token_address); start_cheat_caller_address(campaign_donation.contract_address, sender); let donation_id = campaign_donation.donate_to_campaign(campaign_id, 500); @@ -886,7 +954,6 @@ fn test_get_donation_data_fail_if_not_found() { } fn test_get_donations_by_donor_no_donations() { let (_token_address, sender, campaign_donation, _erc721, _, _) = setup(); - // Fetch donations for sender let donations = campaign_donation.get_donations_by_donor(sender); assert(donations.len() == 0, 'Should have no donations'); @@ -896,10 +963,11 @@ fn test_get_donations_by_donor_no_donations() { fn test_get_donations_by_donor_single_donation() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; - + let donation_token = token_address; // Create new campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id: u256 = campaign_donation.create_campaign('Campaign1', target_amount); + let campaign_id: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -929,11 +997,13 @@ fn test_get_donations_by_donor_single_donation() { fn test_get_donations_by_donor_across_multiple_campaigns() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; - + let donation_token = token_address; // Create two campaigns start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id_1: u256 = campaign_donation.create_campaign('Campaign1', target_amount); - let campaign_id_2: u256 = campaign_donation.create_campaign('Campaign2', target_amount); + let campaign_id_1: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); + let campaign_id_2: u256 = campaign_donation + .create_campaign('Campaign2', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -975,10 +1045,11 @@ fn test_get_donations_by_donor_across_multiple_campaigns() { fn test_get_donations_by_donor_multiple_donations() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); let target_amount = 1000_u256; - + let donation_token = token_address; // Create new campaign start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id: u256 = campaign_donation.create_campaign('Campaign1', target_amount); + let campaign_id: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -1026,11 +1097,13 @@ fn test_get_total_donated_by_donor_no_donations() { #[test] fn test_get_total_donated_by_donor_single_donation() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let donation_token = token_address; // Create new campaign let target_amount = 1000_u256; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id: u256 = campaign_donation.create_campaign('Campaign1', target_amount); + let campaign_id: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -1055,11 +1128,13 @@ fn test_get_total_donated_by_donor_single_donation() { #[test] fn test_get_total_donated_by_donor_multiple_donations_same_campaign() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let donation_token = token_address; // Create new campaign let target_amount = 1000_u256; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id: u256 = campaign_donation.create_campaign('Campaign1', target_amount); + let campaign_id: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -1086,12 +1161,14 @@ fn test_get_total_donated_by_donor_multiple_donations_same_campaign() { #[test] fn test_get_total_donated_by_donor_across_multiple_campaigns() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); - + let donation_token = token_address; // Create two campaigns let target_amount = 1000_u256; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id_1: u256 = campaign_donation.create_campaign('Campaign1', target_amount); - let campaign_id_2: u256 = campaign_donation.create_campaign('Campaign2', target_amount); + let campaign_id_1: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); + let campaign_id_2: u256 = campaign_donation + .create_campaign('Campaign2', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Approve token transfer for campaign contract @@ -1122,6 +1199,7 @@ fn test_protocol_donation_fee_calculation() { let (token_address, sender, campaign_donation, _erc721, protocol_owner, protocol_address) = setup(); let token = _erc721; + let donation_token = token_address; // Set protocol fee to 250 basis points (2.5%) start_cheat_caller_address(campaign_donation.contract_address, protocol_owner); campaign_donation.set_protocol_fee_address(protocol_address); @@ -1131,7 +1209,7 @@ fn test_protocol_donation_fee_calculation() { // Create a campaign and make a donation let target_amount = 1000_u256; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id = campaign_donation.create_campaign('Test', target_amount); + let campaign_id = campaign_donation.create_campaign('Test', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Setup token approval and make donation @@ -1172,6 +1250,7 @@ fn test_protocol_donation_fee_calculation() { #[test] fn test_has_donated_to_campaign_single_donation() { let (token_address, sender, campaign_donation, _erc721, _, _) = setup(); + let donation_token = token_address; // Check that sender has not donated to nonexistent campaign let nonexistent_campaign_id = 42; @@ -1181,7 +1260,8 @@ fn test_has_donated_to_campaign_single_donation() { // Create new campaign let target_amount = 1000_u256; start_cheat_caller_address(campaign_donation.contract_address, sender); - let campaign_id: u256 = campaign_donation.create_campaign('Campaign1', target_amount); + let campaign_id: u256 = campaign_donation + .create_campaign('Campaign1', target_amount, donation_token); stop_cheat_caller_address(campaign_donation.contract_address); // Check that sender has not donated to newly created campaign diff --git a/tests/test_payment_stream.cairo b/tests/test_payment_stream.cairo index 451b587..968310f 100644 --- a/tests/test_payment_stream.cairo +++ b/tests/test_payment_stream.cairo @@ -361,7 +361,6 @@ fn test_stream_metrics_accuracy() { // Get initial metrics let initial_metrics = payment_stream.get_stream_metrics(stream_id); - let stream = payment_stream.get_stream(stream_id); println!("Stream balance: {}", stream.balance); println!("Stream rate per second: {}", stream.rate_per_second); @@ -645,7 +644,8 @@ fn test_withdraw() { // Withdraw to another address let another_recipient = contract_address_const::<'another_recipient'>(); start_cheat_caller_address(payment_stream.contract_address, recipient); - let (withdrawn_to_another, fee_to_another) = payment_stream.withdraw(stream_id, 5000_u256, another_recipient); + let (withdrawn_to_another, fee_to_another) = payment_stream + .withdraw(stream_id, 5000_u256, another_recipient); stop_cheat_caller_address(payment_stream.contract_address); // Verify withdrawal