From 0e1d4dcff29662d3e32b1300f74ac96c9e264d49 Mon Sep 17 00:00:00 2001 From: sBaki92 Date: Thu, 7 Nov 2024 18:51:50 +0100 Subject: [PATCH 1/5] add-carbon-offset-to-claim-and-tests --- src/components/offsetter/interface.cairo | 16 +- src/components/offsetter/offset_handler.cairo | 55 +- tests/test_merkle_tree.cairo | 152 +++-- tests/test_offsetter.cairo | 558 +++++++++++++++++- 4 files changed, 685 insertions(+), 96 deletions(-) diff --git a/src/components/offsetter/interface.cairo b/src/components/offsetter/interface.cairo index ee1217e..0449733 100644 --- a/src/components/offsetter/interface.cairo +++ b/src/components/offsetter/interface.cairo @@ -3,6 +3,7 @@ use carbon_v3::models::carbon_vintage::CarbonVintage; #[starknet::interface] trait IOffsetHandler { + /// Retire carbon credits from one vintage of carbon credits. fn retire_carbon_credits(ref self: TContractState, token_id: u256, cc_amount: u256); @@ -14,10 +15,23 @@ trait IOffsetHandler { ref self: TContractState, token_ids: Span, cc_amounts: Span ); - fn claim( + fn confirm_for_merkle_tree( + ref self: TContractState, from: ContractAddress, amount: u128, timestamp: u128, id: u128, proof: Array:: + ) -> bool; + + fn confirm_offset( ref self: TContractState, amount: u128, timestamp: u128, id: u128, proof: Array:: ); + fn get_allocation_id( + self: @TContractState, from: ContractAddress + ) -> u256; + + + fn get_retirement( + self: @TContractState, token_id: u256, from: ContractAddress + ) -> u256; + /// Get the pending retirement of a vintage for the caller address. fn get_pending_retirement( self: @TContractState, address: ContractAddress, token_id: u256 diff --git a/src/components/offsetter/offset_handler.cairo b/src/components/offsetter/offset_handler.cairo index 8a0d4ae..4628378 100644 --- a/src/components/offsetter/offset_handler.cairo +++ b/src/components/offsetter/offset_handler.cairo @@ -154,34 +154,55 @@ mod OffsetComponent { }; } - fn claim( + fn confirm_for_merkle_tree( ref self: ComponentState, + from: ContractAddress, amount: u128, timestamp: u128, id: u128, proof: Array:: - ) { + ) -> bool { let mut merkle_tree: MerkleTree = MerkleTreeImpl::new(); - let claimee = get_caller_address(); - - // [Verify not already claimed] - let claimed = self.check_claimed(claimee, timestamp, amount, id); - assert(!claimed, 'Already claimed'); // [Verify the proof] let amount_felt: felt252 = amount.into(); - let claimee_felt: felt252 = claimee.into(); + let from_felt: felt252 = from.into(); let timestamp_felt: felt252 = timestamp.into(); let id_felt: felt252 = id.into(); - let intermediate_hash = LegacyHash::hash(claimee_felt, amount_felt); + let intermediate_hash = LegacyHash::hash(from_felt, amount_felt); let intermediate_hash = LegacyHash::hash(intermediate_hash, timestamp_felt); let leaf = LegacyHash::hash(intermediate_hash, id_felt); let root_computed = merkle_tree.compute_root(leaf, proof.span()); let stored_root = self.Offsetter_merkle_root.read(); - assert(root_computed == stored_root, 'Invalid proof'); + if root_computed != stored_root{ + assert(root_computed == stored_root, 'Invalid proof'); + return false; + } + + return true; + } + + fn confirm_offset( + ref self: ComponentState, + amount: u128, + timestamp: u128, + id: u128, + proof: Array:: + ) { + let claimee = get_caller_address(); + + // [Verify not already claimed] + let claimed = self.check_claimed(claimee, timestamp, amount, id); + assert(!claimed, 'Already claimed'); + + // [Verify if the merkle tree claim is possible] + assert!(self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof)); + + //If everything is correct, we offset the carbon credits + self._offset_carbon_credit(claimee, 1, amount.into()); // [Mark as claimed] let allocation = Allocation { @@ -196,8 +217,22 @@ mod OffsetComponent { claimee: claimee, amount: amount, timestamp: timestamp, id: id } ); + } + fn get_allocation_id( + self: @ComponentState, from: ContractAddress + ) -> u256 { + self.Offsetter_allocation_id.read(from) + } + + fn get_retirement( + self: @ComponentState, token_id: u256, from: ContractAddress + ) -> u256 { + self.Offsetter_carbon_retired.read((token_id, from)) + } + + fn get_pending_retirement( self: @ComponentState, address: ContractAddress, token_id: u256 ) -> u256 { diff --git a/tests/test_merkle_tree.cairo b/tests/test_merkle_tree.cairo index 23ae33f..51792c1 100644 --- a/tests/test_merkle_tree.cairo +++ b/tests/test_merkle_tree.cairo @@ -66,34 +66,31 @@ fn test_bob_claims_single_allocation() { start_cheat_caller_address(offsetter_address, bob_address); assert_eq!(contract.get_merkle_root(), root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, proof); - - assert!(contract.check_claimed(bob_address, timestamp, amount, id)); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); } -#[test] -#[should_panic(expected: 'Already claimed')] -fn test_bob_claims_twice() { - /// Test that trying to claim the same allocation twice results in a panic. - let owner_address = contract_address_const::<'OWNER'>(); - let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); - let project_address = default_setup_and_deploy(); - let offsetter_address = deploy_offsetter(project_address); - let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; - - start_cheat_caller_address(offsetter_address, owner_address); - contract.set_merkle_root(root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, proof.clone()); - assert!(contract.check_claimed(bob_address, timestamp, amount, id)); - - contract.claim(amount, timestamp, id, proof); -} +///Keep this test for the confirm_offset tests. +//#[test] +//#[should_panic(expected: 'Already claimed')] +//fn test_bob_claims_twice() { +// /// Test that trying to confirm_for_merkle_tree the same allocation twice results in a panic. +// let owner_address = contract_address_const::<'OWNER'>(); +// let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); +// let project_address = default_setup_and_deploy(); +// let offsetter_address = deploy_offsetter(project_address); +// let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; +// +// start_cheat_caller_address(offsetter_address, owner_address); +// contract.set_merkle_root(root); +// assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); +// +// //start_cheat_caller_address(offsetter_address, bob_address); +// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof.clone()); +// assert!(contract.check_claimed(bob_address, timestamp, amount, id)); +// +// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof); +//} #[test] #[should_panic(expected: 'Invalid proof')] @@ -109,8 +106,8 @@ fn test_claim_with_invalid_address() { let invalid_address = contract_address_const::<'DUMMY'>(); assert!(!contract.check_claimed(invalid_address, timestamp, amount, id)); - start_cheat_caller_address(offsetter_address, invalid_address); - contract.claim(amount, timestamp, id, proof); + //start_cheat_caller_address(offsetter_address, invalid_address); + assert!(!contract.confirm_for_merkle_tree(invalid_address, amount, timestamp, id, proof)); } #[test] @@ -127,8 +124,8 @@ fn test_claim_with_invalid_amount() { let invalid_amount = 0; assert!(!contract.check_claimed(bob_address, timestamp, invalid_amount, id)); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(invalid_amount, timestamp, id, proof); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(!contract.confirm_for_merkle_tree(bob_address, invalid_amount, timestamp, id, proof)); } #[test] @@ -145,8 +142,8 @@ fn test_claim_with_invalid_timestamp() { let invalid_timestamp = 0; assert!(!contract.check_claimed(bob_address, invalid_timestamp, amount, id)); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, invalid_timestamp, id, proof); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(!contract.confirm_for_merkle_tree(bob_address, amount, invalid_timestamp, id, proof)); } #[test] @@ -163,33 +160,34 @@ fn test_claim_with_invalid_proof() { let invalid_proof: Array = array![0x123, 0x1]; assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, invalid_proof); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(!contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, invalid_proof)); } -#[test] -fn test_event_emission_on_claim() { - let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); - let owner_address = contract_address_const::<'OWNER'>(); - let project_address = default_setup_and_deploy(); - let offsetter_address = deploy_offsetter(project_address); - let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; - - start_cheat_caller_address(offsetter_address, owner_address); - contract.set_merkle_root(root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - - let mut spy = spy_events(); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, proof); - - let expected_event = OffsetComponent::Event::AllocationClaimed( - OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } - ); - spy.assert_emitted(@array![(offsetter_address, expected_event)]); - - assert!(contract.check_claimed(bob_address, timestamp, amount, id)); -} +///Keep this test for the confirm_offset tests. +//#[test] +//fn test_event_emission_on_claim() { +// let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); +// let owner_address = contract_address_const::<'OWNER'>(); +// let project_address = default_setup_and_deploy(); +// let offsetter_address = deploy_offsetter(project_address); +// let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; +// +// start_cheat_caller_address(offsetter_address, owner_address); +// contract.set_merkle_root(root); +// assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); +// +// let mut spy = spy_events(); +// //start_cheat_caller_address(offsetter_address, bob_address); +// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof); +// +// let expected_event = OffsetComponent::Event::AllocationClaimed( +// OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } +// ); +// spy.assert_emitted(@array![(offsetter_address, expected_event)]); +// +// assert!(contract.check_claimed(bob_address, timestamp, amount, id)); +//} #[test] fn test_claim_after_root_update() { @@ -208,14 +206,13 @@ fn test_claim_after_root_update() { contract.set_merkle_root(new_root); assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, new_proof); - assert!(contract.check_claimed(bob_address, timestamp, amount, id)); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, new_proof)); } #[test] fn test_alice_claims_in_second_wave() { - /// Test that Bob can claim his allocation from the first wave and Alice can claim her allocation from the second wave. + /// Test that Bob can confirm his allocation from the first wave and Alice can confirm her allocation from the second wave. let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); let owner_address = contract_address_const::<'OWNER'>(); let project_address = default_setup_and_deploy(); @@ -226,15 +223,8 @@ fn test_alice_claims_in_second_wave() { contract.set_merkle_root(root); assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - let mut spy = spy_events(); - start_cheat_caller_address(offsetter_address, bob_address); - contract.claim(amount, timestamp, id, proof); - - let expected_event = OffsetComponent::Event::AllocationClaimed( - OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } - ); - spy.assert_emitted(@array![(offsetter_address, expected_event)]); - assert!(contract.check_claimed(bob_address, timestamp, amount, id)); + //start_cheat_caller_address(offsetter_address, bob_address); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); let (new_root, alice_address, amount, timestamp, id, proof) = get_alice_second_wave_allocation(); @@ -242,14 +232,13 @@ fn test_alice_claims_in_second_wave() { contract.set_merkle_root(new_root); assert!(!contract.check_claimed(alice_address, timestamp, amount, id)); - start_cheat_caller_address(offsetter_address, alice_address); - contract.claim(amount, timestamp, id, proof); - assert!(contract.check_claimed(alice_address, timestamp, amount, id)); + //start_cheat_caller_address(offsetter_address, alice_address); + assert!(contract.confirm_for_merkle_tree(alice_address, amount, timestamp, id, proof)); } #[test] fn test_john_claims_multiple_allocations() { - /// Test that John can claim two of his three allocations from the first wave, and the remaining one from the second wave. + /// Test that John can confirm_for_merkle_tree two of his three allocations from the first wave, and the remaining one from the second wave. let ( root, new_root, @@ -284,18 +273,13 @@ fn test_john_claims_multiple_allocations() { assert!(!contract.check_claimed(john_address, timestamp2, amount2, id_2)); assert!(!contract.check_claimed(john_address, timestamp3, amount3, id_3)); - start_cheat_caller_address(offsetter_address, john_address); - contract.claim(amount1, timestamp1, id_1, proof1); - contract.claim(amount2, timestamp2, id_2, proof2); - assert!(contract.check_claimed(john_address, timestamp1, amount1, id_1)); - assert!(contract.check_claimed(john_address, timestamp2, amount2, id_2)); - assert!(!contract.check_claimed(john_address, timestamp3, amount3, id_3)); + //start_cheat_caller_address(offsetter_address, john_address); + assert!(contract.confirm_for_merkle_tree(john_address, amount1, timestamp1, id_1, proof1)); + assert!(contract.confirm_for_merkle_tree(john_address, amount2, timestamp2, id_2, proof2)); start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(new_root); - start_cheat_caller_address(offsetter_address, john_address); - contract.claim(amount4, timestamp4, id_4, proof4); - assert!(contract.check_claimed(john_address, timestamp4, amount4, id_4)); - assert!(!contract.check_claimed(john_address, timestamp3, amount3, id_3)); + //start_cheat_caller_address(offsetter_address, john_address); + assert!(contract.confirm_for_merkle_tree(john_address, amount4, timestamp4, id_4, proof4)); } diff --git a/tests/test_offsetter.cairo b/tests/test_offsetter.cairo index 8a66891..f5a0835 100644 --- a/tests/test_offsetter.cairo +++ b/tests/test_offsetter.cairo @@ -22,7 +22,7 @@ use carbon_v3::components::erc1155::interface::{IERC1155Dispatcher, IERC1155Disp use carbon_v3::components::offsetter::interface::{ IOffsetHandlerDispatcher, IOffsetHandlerDispatcherTrait }; - +use carbon_v3::components::offsetter::OffsetComponent; // Contracts use carbon_v3::contracts::project::{ @@ -57,6 +57,12 @@ struct Contracts { } +/// Utils to import mock data +use super::tests_lib::{ + MERKLE_ROOT_FIRST_WAVE, MERKLE_ROOT_SECOND_WAVE, get_bob_first_wave_allocation, + get_bob_second_wave_allocation, get_alice_second_wave_allocation, get_john_multiple_allocations +}; + // // Tests // @@ -506,3 +512,553 @@ fn test_get_carbon_retired_no_retired() { assert(carbon_retired == 0.into(), 'Error about carbon retired'); } + +/// confirm_offset + +#[test] +fn test_confirm_offset() { + /// Test a simple confirm offset scenario where Bob claims his retirement from the first wave. + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, bob_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(bob_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, bob_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + bob_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(bob_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(bob_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + let current_retirement = offsetter.get_retirement(token_id, bob_address); + let new_retirement = current_retirement + amount.clone().into(); + + assert!(!offsetter.check_claimed(bob_address, timestamp, amount, id)); + offsetter.confirm_offset(amount, timestamp, id, proof); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + + assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement) + +} + +#[test] +#[should_panic(expected: 'Already claimed')] +fn test_bob_confirms_twice() { + /// Test that Bob trying to confirm the same offset twice, results in a panic. + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, bob_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(bob_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, bob_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + bob_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(bob_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(bob_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + offsetter.confirm_offset(amount, timestamp, id, proof.clone()); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + + offsetter.confirm_offset(amount, timestamp, id, proof); +} + + +#[test] +fn test_events_emission_on_claim_confirmation() { + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, bob_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(bob_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, bob_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + bob_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(bob_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(bob_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + let current_retirement = offsetter.get_retirement(token_id, bob_address); + let new_retirement = current_retirement + amount.clone().into(); + + let mut spy = spy_events(); + offsetter.confirm_offset(amount, timestamp, id, proof); + + + let first_expected_event = OffsetComponent::Event::Retired( + OffsetComponent::Retired { from: bob_address, project : project_address, + token_id : token_id, old_amount : current_retirement, new_amount : new_retirement } + ); + + let second_expected_event = OffsetComponent::Event::AllocationClaimed( + OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } + ); + + spy.assert_emitted(@array![(offsetter_address, first_expected_event), (offsetter_address, second_expected_event)]); + + assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + +} + + +#[test] +#[should_panic(expected: 'Invalid proof')] +fn test_claim_confirmation_with_invalid_amount() { + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, bob_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(bob_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, bob_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + bob_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(bob_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(bob_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + let invalid_amount = 0; + + offsetter.confirm_offset(invalid_amount, timestamp, id, proof); + +} + +#[test] +fn test_alice_confirms_in_second_wawe() { + /// Test that Bob can confirm his offset from the first wave and Alice can confirm her offset from the second wave. + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, bob_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(bob_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, bob_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, bob_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + bob_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(bob_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(bob_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + let current_retirement = offsetter.get_retirement(token_id, bob_address); + let new_retirement = current_retirement + amount.clone().into(); + + assert!(!offsetter.check_claimed(bob_address, timestamp, amount, id)); + offsetter.confirm_offset(amount, timestamp, id, proof); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + + assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement); + + stop_cheat_caller_address(erc20_address); + stop_cheat_caller_address(project_address); + + let (new_root, alice_address, amount, timestamp, id, proof) = get_alice_second_wave_allocation(); + + start_cheat_caller_address(offsetter_address, alice_address); + start_cheat_caller_address(project_address, owner_address); + + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, alice_address, minter_address, cc_to_mint); + let initial_balance = project.balance_of(alice_address, token_id); + + let amount_to_offset: u256 = amount.into(); + + + start_cheat_caller_address(offsetter_address, alice_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(new_root); + + start_cheat_caller_address(project_address, alice_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + let mut spy = spy_events(); + start_cheat_caller_address(offsetter_address, alice_address); + start_cheat_caller_address(project_address, offsetter_address); + offsetter.retire_carbon_credits(token_id, amount_to_offset); + + let expected_event = helper_expected_transfer_event( + project_address, + offsetter_address, + alice_address, + offsetter_address, + array![token_id].span(), + amount_to_offset + ); + + spy.assert_emitted(@array![(project_address, expected_event)]); + + let carbon_pending = offsetter.get_pending_retirement(alice_address, token_id); + assert(carbon_pending == amount_to_offset, 'Carbon pending is wrong'); + let final_balance = project.balance_of(alice_address, token_id); + assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); + + let current_retirement = offsetter.get_retirement(token_id, alice_address); + let new_retirement = current_retirement + amount.clone().into(); + + assert!(!offsetter.check_claimed(alice_address, timestamp, amount, id)); + offsetter.confirm_offset(amount, timestamp, id, proof); + assert!(offsetter.check_claimed(alice_address, timestamp, amount, id)); + + assert!(offsetter.get_retirement(token_id, alice_address) == new_retirement); +} + +#[test] +fn test_john_confirms_multiple_allocations() { + /// Test that John can two of his three offset from the first allocations wave, and the remaining one from the second wave. + let owner_address = contract_address_const::<'OWNER'>(); + let project_address = default_setup_and_deploy(); + let offsetter_address = deploy_offsetter(project_address); + + let ( + root, + new_root, + john_address, + amount1, + timestamp1, + id_1, + amount2, + timestamp2, + id_2, + _, + _, + _, + amount4, + timestamp4, + id_4, + proof1, + proof2, + _, + proof4 + ) = + get_john_multiple_allocations(); + + let erc20_address = deploy_erc20(); + let minter_address = deploy_minter(project_address, erc20_address); + let token_id: u256 = 1; + + start_cheat_caller_address(offsetter_address, john_address); + start_cheat_caller_address(project_address, owner_address); + + let project = IProjectDispatcher { contract_address: project_address }; + project.grant_minter_role(minter_address); + project.grant_offsetter_role(offsetter_address); + stop_cheat_caller_address(project_address); + + let vintages = IVintageDispatcher { contract_address: project_address }; + let initial_total_supply = vintages.get_initial_project_cc_supply(); + let cc_to_mint = initial_total_supply / 10; // 10% of the total supply + + buy_utils(owner_address, john_address, minter_address, cc_to_mint); + + let amount1_to_offset: u256 = amount1.into(); + let amount2_to_offset: u256 = amount2.into(); + let amount4_to_offset: u256 = amount4.into(); + + start_cheat_caller_address(project_address, owner_address); + vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); + + start_cheat_caller_address(offsetter_address, john_address); + start_cheat_caller_address(project_address, offsetter_address); + + let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(root); + + start_cheat_caller_address(project_address, john_address); + project.set_approval_for_all(offsetter_address, true); + stop_cheat_caller_address(erc20_address); + + + start_cheat_caller_address(offsetter_address, john_address); + start_cheat_caller_address(project_address, offsetter_address); + + offsetter.retire_carbon_credits(token_id, amount1_to_offset); + assert!(!offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); + offsetter.confirm_offset(amount1, timestamp1, id_1, proof1); + + offsetter.retire_carbon_credits(token_id, amount2_to_offset); + assert!(!offsetter.check_claimed(john_address, timestamp2, amount2, id_2)); + offsetter.confirm_offset(amount2, timestamp2, id_2, proof2); + + assert!(offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); + assert!(offsetter.check_claimed(john_address, timestamp2, amount2, id_2)); + + + start_cheat_caller_address(offsetter_address, owner_address); + offsetter.set_merkle_root(new_root); + + start_cheat_caller_address(offsetter_address, john_address); + start_cheat_caller_address(project_address, offsetter_address); + + offsetter.retire_carbon_credits(token_id, amount4_to_offset); + assert!(!offsetter.check_claimed(john_address, timestamp4, amount4, id_4)); + offsetter.confirm_offset(amount4, timestamp4, id_4, proof4); + + assert!(offsetter.check_claimed(john_address, timestamp4, amount4, id_4)); + +} \ No newline at end of file From 877121b2802fb25271a49c75ed09941c0ab97cb7 Mon Sep 17 00:00:00 2001 From: tekkac Date: Fri, 8 Nov 2024 11:31:22 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=9A=A8=20fix=20scarb=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/offsetter/interface.cairo | 16 ++++----- src/components/offsetter/offset_handler.cairo | 11 +++--- tests/test_offsetter.cairo | 36 ++++++++++--------- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/components/offsetter/interface.cairo b/src/components/offsetter/interface.cairo index 0449733..0db50e8 100644 --- a/src/components/offsetter/interface.cairo +++ b/src/components/offsetter/interface.cairo @@ -3,7 +3,6 @@ use carbon_v3::models::carbon_vintage::CarbonVintage; #[starknet::interface] trait IOffsetHandler { - /// Retire carbon credits from one vintage of carbon credits. fn retire_carbon_credits(ref self: TContractState, token_id: u256, cc_amount: u256); @@ -16,21 +15,22 @@ trait IOffsetHandler { ); fn confirm_for_merkle_tree( - ref self: TContractState, from: ContractAddress, amount: u128, timestamp: u128, id: u128, proof: Array:: + ref self: TContractState, + from: ContractAddress, + amount: u128, + timestamp: u128, + id: u128, + proof: Array:: ) -> bool; fn confirm_offset( ref self: TContractState, amount: u128, timestamp: u128, id: u128, proof: Array:: ); - fn get_allocation_id( - self: @TContractState, from: ContractAddress - ) -> u256; + fn get_allocation_id(self: @TContractState, from: ContractAddress) -> u256; - fn get_retirement( - self: @TContractState, token_id: u256, from: ContractAddress - ) -> u256; + fn get_retirement(self: @TContractState, token_id: u256, from: ContractAddress) -> u256; /// Get the pending retirement of a vintage for the caller address. fn get_pending_retirement( diff --git a/src/components/offsetter/offset_handler.cairo b/src/components/offsetter/offset_handler.cairo index 4628378..7cd7d53 100644 --- a/src/components/offsetter/offset_handler.cairo +++ b/src/components/offsetter/offset_handler.cairo @@ -177,14 +177,14 @@ mod OffsetComponent { let root_computed = merkle_tree.compute_root(leaf, proof.span()); let stored_root = self.Offsetter_merkle_root.read(); - if root_computed != stored_root{ + if root_computed != stored_root { assert(root_computed == stored_root, 'Invalid proof'); return false; } - + return true; } - + fn confirm_offset( ref self: ComponentState, amount: u128, @@ -217,12 +217,9 @@ mod OffsetComponent { claimee: claimee, amount: amount, timestamp: timestamp, id: id } ); - } - fn get_allocation_id( - self: @ComponentState, from: ContractAddress - ) -> u256 { + fn get_allocation_id(self: @ComponentState, from: ContractAddress) -> u256 { self.Offsetter_allocation_id.read(from) } diff --git a/tests/test_offsetter.cairo b/tests/test_offsetter.cairo index f5a0835..80cf63e 100644 --- a/tests/test_offsetter.cairo +++ b/tests/test_offsetter.cairo @@ -589,7 +589,6 @@ fn test_confirm_offset() { assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement) - } #[test] @@ -737,20 +736,29 @@ fn test_events_emission_on_claim_confirmation() { let mut spy = spy_events(); offsetter.confirm_offset(amount, timestamp, id, proof); - let first_expected_event = OffsetComponent::Event::Retired( - OffsetComponent::Retired { from: bob_address, project : project_address, - token_id : token_id, old_amount : current_retirement, new_amount : new_retirement } + OffsetComponent::Retired { + from: bob_address, + project: project_address, + token_id: token_id, + old_amount: current_retirement, + new_amount: new_retirement + } ); let second_expected_event = OffsetComponent::Event::AllocationClaimed( OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } ); - - spy.assert_emitted(@array![(offsetter_address, first_expected_event), (offsetter_address, second_expected_event)]); - assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + spy + .assert_emitted( + @array![ + (offsetter_address, first_expected_event), + (offsetter_address, second_expected_event) + ] + ); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); } @@ -823,7 +831,6 @@ fn test_claim_confirmation_with_invalid_amount() { let invalid_amount = 0; offsetter.confirm_offset(invalid_amount, timestamp, id, proof); - } #[test] @@ -900,11 +907,12 @@ fn test_alice_confirms_in_second_wawe() { assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement); - + stop_cheat_caller_address(erc20_address); stop_cheat_caller_address(project_address); - let (new_root, alice_address, amount, timestamp, id, proof) = get_alice_second_wave_allocation(); + let (new_root, alice_address, amount, timestamp, id, proof) = + get_alice_second_wave_allocation(); start_cheat_caller_address(offsetter_address, alice_address); start_cheat_caller_address(project_address, owner_address); @@ -922,7 +930,6 @@ fn test_alice_confirms_in_second_wawe() { let amount_to_offset: u256 = amount.into(); - start_cheat_caller_address(offsetter_address, alice_address); start_cheat_caller_address(project_address, offsetter_address); @@ -1033,10 +1040,9 @@ fn test_john_confirms_multiple_allocations() { project.set_approval_for_all(offsetter_address, true); stop_cheat_caller_address(erc20_address); - start_cheat_caller_address(offsetter_address, john_address); start_cheat_caller_address(project_address, offsetter_address); - + offsetter.retire_carbon_credits(token_id, amount1_to_offset); assert!(!offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); offsetter.confirm_offset(amount1, timestamp1, id_1, proof1); @@ -1048,7 +1054,6 @@ fn test_john_confirms_multiple_allocations() { assert!(offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); assert!(offsetter.check_claimed(john_address, timestamp2, amount2, id_2)); - start_cheat_caller_address(offsetter_address, owner_address); offsetter.set_merkle_root(new_root); @@ -1060,5 +1065,4 @@ fn test_john_confirms_multiple_allocations() { offsetter.confirm_offset(amount4, timestamp4, id_4, proof4); assert!(offsetter.check_claimed(john_address, timestamp4, amount4, id_4)); - -} \ No newline at end of file +} From fc8ae12bb3ed12c09135ef46e034929c527177df Mon Sep 17 00:00:00 2001 From: sBaki92 Date: Mon, 11 Nov 2024 19:13:27 +0100 Subject: [PATCH 3/5] update offsetter tests and offset confirmation --- src/components/offsetter/interface.cairo | 4 +- src/components/offsetter/offset_handler.cairo | 2 +- tests/test_merkle_tree.cairo | 57 ------------------- 3 files changed, 4 insertions(+), 59 deletions(-) diff --git a/src/components/offsetter/interface.cairo b/src/components/offsetter/interface.cairo index 0db50e8..2f045ed 100644 --- a/src/components/offsetter/interface.cairo +++ b/src/components/offsetter/interface.cairo @@ -13,7 +13,8 @@ trait IOffsetHandler { fn retire_list_carbon_credits( ref self: TContractState, token_ids: Span, cc_amounts: Span ); - + + ///Verify and validate the proof on the Merkle tree side to confirm the offset. fn confirm_for_merkle_tree( ref self: TContractState, from: ContractAddress, @@ -23,6 +24,7 @@ trait IOffsetHandler { proof: Array:: ) -> bool; + ///Verify on the business logic side, confirm on the Merkle tree side, and perform the offset action. fn confirm_offset( ref self: TContractState, amount: u128, timestamp: u128, id: u128, proof: Array:: ); diff --git a/src/components/offsetter/offset_handler.cairo b/src/components/offsetter/offset_handler.cairo index 7cd7d53..29e24ad 100644 --- a/src/components/offsetter/offset_handler.cairo +++ b/src/components/offsetter/offset_handler.cairo @@ -199,7 +199,7 @@ mod OffsetComponent { assert(!claimed, 'Already claimed'); // [Verify if the merkle tree claim is possible] - assert!(self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof)); + assert(self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof), 'Invalid proof'); //If everything is correct, we offset the carbon credits self._offset_carbon_credit(claimee, 1, amount.into()); diff --git a/tests/test_merkle_tree.cairo b/tests/test_merkle_tree.cairo index 51792c1..7b05006 100644 --- a/tests/test_merkle_tree.cairo +++ b/tests/test_merkle_tree.cairo @@ -66,32 +66,9 @@ fn test_bob_claims_single_allocation() { start_cheat_caller_address(offsetter_address, bob_address); assert_eq!(contract.get_merkle_root(), root); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); } -///Keep this test for the confirm_offset tests. -//#[test] -//#[should_panic(expected: 'Already claimed')] -//fn test_bob_claims_twice() { -// /// Test that trying to confirm_for_merkle_tree the same allocation twice results in a panic. -// let owner_address = contract_address_const::<'OWNER'>(); -// let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); -// let project_address = default_setup_and_deploy(); -// let offsetter_address = deploy_offsetter(project_address); -// let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; -// -// start_cheat_caller_address(offsetter_address, owner_address); -// contract.set_merkle_root(root); -// assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); -// -// //start_cheat_caller_address(offsetter_address, bob_address); -// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof.clone()); -// assert!(contract.check_claimed(bob_address, timestamp, amount, id)); -// -// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof); -//} - #[test] #[should_panic(expected: 'Invalid proof')] fn test_claim_with_invalid_address() { @@ -106,7 +83,6 @@ fn test_claim_with_invalid_address() { let invalid_address = contract_address_const::<'DUMMY'>(); assert!(!contract.check_claimed(invalid_address, timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, invalid_address); assert!(!contract.confirm_for_merkle_tree(invalid_address, amount, timestamp, id, proof)); } @@ -124,7 +100,6 @@ fn test_claim_with_invalid_amount() { let invalid_amount = 0; assert!(!contract.check_claimed(bob_address, timestamp, invalid_amount, id)); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(!contract.confirm_for_merkle_tree(bob_address, invalid_amount, timestamp, id, proof)); } @@ -142,7 +117,6 @@ fn test_claim_with_invalid_timestamp() { let invalid_timestamp = 0; assert!(!contract.check_claimed(bob_address, invalid_timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(!contract.confirm_for_merkle_tree(bob_address, amount, invalid_timestamp, id, proof)); } @@ -160,35 +134,9 @@ fn test_claim_with_invalid_proof() { let invalid_proof: Array = array![0x123, 0x1]; assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(!contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, invalid_proof)); } -///Keep this test for the confirm_offset tests. -//#[test] -//fn test_event_emission_on_claim() { -// let (root, bob_address, amount, timestamp, id, proof) = get_bob_first_wave_allocation(); -// let owner_address = contract_address_const::<'OWNER'>(); -// let project_address = default_setup_and_deploy(); -// let offsetter_address = deploy_offsetter(project_address); -// let contract = IOffsetHandlerDispatcher { contract_address: offsetter_address }; -// -// start_cheat_caller_address(offsetter_address, owner_address); -// contract.set_merkle_root(root); -// assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); -// -// let mut spy = spy_events(); -// //start_cheat_caller_address(offsetter_address, bob_address); -// contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof); -// -// let expected_event = OffsetComponent::Event::AllocationClaimed( -// OffsetComponent::AllocationClaimed { claimee: bob_address, amount, timestamp, id } -// ); -// spy.assert_emitted(@array![(offsetter_address, expected_event)]); -// -// assert!(contract.check_claimed(bob_address, timestamp, amount, id)); -//} - #[test] fn test_claim_after_root_update() { /// Test that an unclaimed allocation from the first wave can still be claimed after setting a new Merkle root. @@ -206,7 +154,6 @@ fn test_claim_after_root_update() { contract.set_merkle_root(new_root); assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, new_proof)); } @@ -223,7 +170,6 @@ fn test_alice_claims_in_second_wave() { contract.set_merkle_root(root); assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, bob_address); assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); let (new_root, alice_address, amount, timestamp, id, proof) = @@ -232,7 +178,6 @@ fn test_alice_claims_in_second_wave() { contract.set_merkle_root(new_root); assert!(!contract.check_claimed(alice_address, timestamp, amount, id)); - //start_cheat_caller_address(offsetter_address, alice_address); assert!(contract.confirm_for_merkle_tree(alice_address, amount, timestamp, id, proof)); } @@ -273,13 +218,11 @@ fn test_john_claims_multiple_allocations() { assert!(!contract.check_claimed(john_address, timestamp2, amount2, id_2)); assert!(!contract.check_claimed(john_address, timestamp3, amount3, id_3)); - //start_cheat_caller_address(offsetter_address, john_address); assert!(contract.confirm_for_merkle_tree(john_address, amount1, timestamp1, id_1, proof1)); assert!(contract.confirm_for_merkle_tree(john_address, amount2, timestamp2, id_2, proof2)); start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(new_root); - //start_cheat_caller_address(offsetter_address, john_address); assert!(contract.confirm_for_merkle_tree(john_address, amount4, timestamp4, id_4, proof4)); } From 7e8b4b6225cce777f5a48162ae7a4fb43e79d3a1 Mon Sep 17 00:00:00 2001 From: sBaki <167719173+sBaki92@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:53:43 +0100 Subject: [PATCH 4/5] Update tests/test_offsetter.cairo Co-authored-by: Tekkac --- tests/test_offsetter.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_offsetter.cairo b/tests/test_offsetter.cairo index 80cf63e..3aac557 100644 --- a/tests/test_offsetter.cairo +++ b/tests/test_offsetter.cairo @@ -834,7 +834,7 @@ fn test_claim_confirmation_with_invalid_amount() { } #[test] -fn test_alice_confirms_in_second_wawe() { +fn test_alice_confirms_in_second_wave() { /// Test that Bob can confirm his offset from the first wave and Alice can confirm her offset from the second wave. let owner_address = contract_address_const::<'OWNER'>(); let project_address = default_setup_and_deploy(); From 3409272974c7b1d0ffe5c4f858e9406c4828a623 Mon Sep 17 00:00:00 2001 From: tekkac Date: Tue, 12 Nov 2024 13:24:03 +0100 Subject: [PATCH 5/5] scarb fmt --- src/components/offsetter/interface.cairo | 2 +- src/components/offsetter/offset_handler.cairo | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/offsetter/interface.cairo b/src/components/offsetter/interface.cairo index 2f045ed..a86dfae 100644 --- a/src/components/offsetter/interface.cairo +++ b/src/components/offsetter/interface.cairo @@ -13,7 +13,7 @@ trait IOffsetHandler { fn retire_list_carbon_credits( ref self: TContractState, token_ids: Span, cc_amounts: Span ); - + ///Verify and validate the proof on the Merkle tree side to confirm the offset. fn confirm_for_merkle_tree( ref self: TContractState, diff --git a/src/components/offsetter/offset_handler.cairo b/src/components/offsetter/offset_handler.cairo index 29e24ad..eae2528 100644 --- a/src/components/offsetter/offset_handler.cairo +++ b/src/components/offsetter/offset_handler.cairo @@ -199,7 +199,9 @@ mod OffsetComponent { assert(!claimed, 'Already claimed'); // [Verify if the merkle tree claim is possible] - assert(self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof), 'Invalid proof'); + assert( + self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof), 'Invalid proof' + ); //If everything is correct, we offset the carbon credits self._offset_carbon_credit(claimee, 1, amount.into());