From 798d7defb8f7aaad200e00f064f464e2bd2929aa Mon Sep 17 00:00:00 2001 From: julienbrs Date: Tue, 16 Jul 2024 17:42:24 +0200 Subject: [PATCH 1/9] version: update snfoundry to 0.26.0, scarb 2.6.0 --- .github/workflows/tests.yml | 2 +- Scarb.toml | 8 +++--- src/components/metadata.cairo | 6 ++-- tests/tests_lib.cairo | 52 +++++++++++++++++------------------ 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 24ad508..c6e0de1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,7 +21,7 @@ jobs: - name: Setup snfoundry uses: foundry-rs/setup-snfoundry@v3 with: - starknet-foundry-version: "0.18.0" + starknet-foundry-version: "0.26.0" - name: Run Cairo tests id: cairo_tests diff --git a/Scarb.toml b/Scarb.toml index 114ea54..cc0d38e 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -3,14 +3,14 @@ name = "carbon_v3" version = "0.1.0" [dependencies] -starknet = ">=2.5.3" -alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.5.4" } -alexandria_numeric = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.5.4" } +starknet = ">=2.6.0" +alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.6.0" } +alexandria_numeric = { git = "https://github.com/keep-starknet-strange/alexandria", tag = "cairo-v2.6.0" } openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.10.0" } erc4906 = { git = "https://github.com/carbonable-labs/cairo-erc-4906" } [dev-dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.18.0" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.26.0" } [scripts] test = "snforge test" diff --git a/src/components/metadata.cairo b/src/components/metadata.cairo index 3b4bb1a..3781c3c 100644 --- a/src/components/metadata.cairo +++ b/src/components/metadata.cairo @@ -62,10 +62,10 @@ mod TestMetadataComponent { #[test] fn test_metadata() { - let class = declare('TestContract'); - let metadata_class = declare('TestMetadata'); + let class = declare("TestContract").expect('Declaration failed'); + let metadata_class = declare("TestMetadata").expect('Declaration failed'); - let contract_address = class.deploy(@array![]).unwrap(); + let (contract_address, _) = class.deploy(@array![]).expect('Deployment failed'); let dispatcher = IMetadataHandlerDispatcher { contract_address }; dispatcher.set_uri(metadata_class.class_hash); diff --git a/tests/tests_lib.cairo b/tests/tests_lib.cairo index 373ff71..76ebb7c 100644 --- a/tests/tests_lib.cairo +++ b/tests/tests_lib.cairo @@ -6,7 +6,8 @@ use starknet::{ContractAddress, contract_address_const}; use openzeppelin::utils::serde::SerializedAppend; use snforge_std as snf; -use snforge_std::{CheatTarget, ContractClassTrait, EventSpy, SpyOn, start_prank, stop_prank}; +use snforge_std::{ContractClassTrait, EventSpy, spy_events, EventSpyTrait, + EventSpyAssertionsTrait, start_cheat_caller_address, stop_cheat_caller_address}; use alexandria_storage::list::{List, ListTrait}; // Models @@ -125,7 +126,7 @@ fn share_to_buy_amount(minter_address: ContractAddress, share: u256) -> u256 { /// fn deploy_project() -> (ContractAddress, EventSpy) { - let contract = snf::declare('Project'); + let contract = snf::declare("Project").expect('Declaration failed'); let uri = 'uri'; let starting_year: u64 = 2024; let number_of_years: u64 = 20; @@ -135,9 +136,8 @@ fn deploy_project() -> (ContractAddress, EventSpy) { starting_year.into(), number_of_years.into() ]; - let contract_address = contract.deploy(@calldata).unwrap(); - - let mut spy = snf::spy_events(SpyOn::One(contract_address)); + let (contract_address, _) = contract.deploy(@calldata).expect('Deployment failed'); + let mut spy = spy_events(); (contract_address, spy) } @@ -151,7 +151,7 @@ fn setup_project( let vintages = IVintageDispatcher { contract_address }; // Fake the owner to call set_absorptions and set_project_carbon which can only be run by owner let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - start_prank(CheatTarget::One(contract_address), owner_address); + start_cheat_caller_address(contract_address, owner_address); vintages.set_vintages(absorptions, 2024); vintages.set_project_carbon(project_carbon); @@ -167,15 +167,15 @@ fn default_setup_and_deploy() -> (ContractAddress, EventSpy) { /// Deploys the offsetter contract. fn deploy_offsetter(project_address: ContractAddress) -> (ContractAddress, EventSpy) { - let contract = snf::declare('Offsetter'); + let contract = snf::declare("Offsetter").expect('Declaration failed'); let owner: ContractAddress = contract_address_const::<'OWNER'>(); let mut calldata: Array = array![]; calldata.append(project_address.into()); calldata.append(owner.into()); - let contract_address = contract.deploy(@calldata).unwrap(); + let (contract_address, _) = contract.deploy(@calldata).expect('Deployment failed'); - let mut spy = snf::spy_events(SpyOn::One(contract_address)); + let mut spy = spy_events(); (contract_address, spy) } @@ -184,7 +184,7 @@ fn deploy_offsetter(project_address: ContractAddress) -> (ContractAddress, Event fn deploy_minter( project_address: ContractAddress, payment_address: ContractAddress ) -> (ContractAddress, EventSpy) { - let contract = snf::declare('Minter'); + let contract = snf::declare("Minter").expect('Declaration failed'); let owner: ContractAddress = contract_address_const::<'OWNER'>(); let public_sale: bool = true; let max_value: felt252 = 8000000000; @@ -200,21 +200,21 @@ fn deploy_minter( owner.into() ]; - let contract_address = contract.deploy(@calldata).unwrap(); - let mut spy = snf::spy_events(SpyOn::One(contract_address)); + let (contract_address, _) = contract.deploy(@calldata).expect('Deployment failed'); + let mut spy = spy_events(); (contract_address, spy) } /// Deploy erc20 contract. fn deploy_erc20() -> (ContractAddress, EventSpy) { - let contract = snf::declare('USDCarb'); + let contract = snf::declare("USDCarb").expect('Declaration failed'); let owner: ContractAddress = contract_address_const::<'OWNER'>(); let mut calldata: Array = array![]; calldata.append(owner.into()); calldata.append(owner.into()); - let contract_address = contract.deploy(@calldata).unwrap(); + let (contract_address, _) = contract.deploy(@calldata).expect('Deployment failed'); - let mut spy = snf::spy_events(SpyOn::One(contract_address)); + let mut spy = spy_events(); (contract_address, spy) } @@ -263,28 +263,28 @@ fn buy_utils( share: u256 ) { // [Prank] Use caller (usually user) as caller for the Minter contract - start_prank(CheatTarget::One(minter_address), caller_address); + start_cheat_caller_address(minter_address, caller_address); let minter = IMintDispatcher { contract_address: minter_address }; let erc20_address: ContractAddress = minter.get_payment_token_address(); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; let amount_to_buy = share_to_buy_amount(minter_address, share); // [Prank] Use owner as caller for the ERC20 contract - start_prank(CheatTarget::One(erc20_address), owner_address); // Owner holds initial supply + start_cheat_caller_address(erc20_address, owner_address); // Owner holds initial supply erc20.transfer(caller_address, amount_to_buy); // [Prank] Use caller address (usually user) as caller for the ERC20 contract - start_prank(CheatTarget::One(erc20_address), caller_address); + start_cheat_caller_address(erc20_address, caller_address); erc20.approve(minter_address, amount_to_buy); // [Prank] Use Minter as caller for the ERC20 contract - start_prank(CheatTarget::One(erc20_address), minter_address); + start_cheat_caller_address(erc20_address, minter_address); // [Prank] Use caller (usually user) as caller for the Minter contract - start_prank(CheatTarget::One(minter_address), caller_address); + start_cheat_caller_address(minter_address, caller_address); minter.public_buy(amount_to_buy, false); - stop_prank(CheatTarget::One(erc20_address)); - stop_prank(CheatTarget::One(minter_address)); + stop_cheat_caller_address(minter_address); + stop_cheat_caller_address(erc20_address); } @@ -319,14 +319,14 @@ fn perform_fuzzed_transfer( // let vintages = IVintageDispatcher { contract_address: project_address }; let project = IProjectDispatcher { contract_address: project_address }; // Setup Roles for the contracts - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); project.grant_minter_role(minter_address); - stop_prank(CheatTarget::One(project_address)); + start_cheat_caller_address(project_address, minter_address); // assert(vintages.is_setup(), 'Error during setup'); buy_utils(owner_address, user_address, minter_address, share); - start_prank(CheatTarget::One(project_address), user_address); + start_cheat_caller_address(project_address, user_address); let token_id = 1; let initial_balance = project.balance_of(user_address, token_id); @@ -340,7 +340,7 @@ fn perform_fuzzed_transfer( let balance_receiver = project.balance_of(receiver_address, token_id); assert(equals_with_error(balance_receiver, amount, 10), 'Error balance receiver 1'); - start_prank(CheatTarget::One(project_address), receiver_address); + start_cheat_caller_address(project_address, receiver_address); project .safe_transfer_from( receiver_address, user_address, token_id, amount.into(), array![].span() From d25ef90976d738377135fbd62d3b8ed33ce3c34d Mon Sep 17 00:00:00 2001 From: julienbrs Date: Tue, 16 Jul 2024 17:42:47 +0200 Subject: [PATCH 2/9] update test_mint snfoundry 0.26.0 --- tests/test_mint.cairo | 415 ++++++++++-------------------------------- 1 file changed, 100 insertions(+), 315 deletions(-) diff --git a/tests/test_mint.cairo b/tests/test_mint.cairo index 91fa668..c3738ca 100644 --- a/tests/test_mint.cairo +++ b/tests/test_mint.cairo @@ -8,14 +8,12 @@ use starknet::{ContractAddress, contract_address_const}; // External deps -use openzeppelin::tests::utils::constants as c; use openzeppelin::utils::serde::SerializedAppend; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use snforge_std as snf; use snforge_std::{ - CheatTarget, ContractClassTrait, test_address, spy_events, EventSpy, SpyOn, EventAssertions, - start_warp, start_prank, stop_prank + ContractClassTrait, test_address, spy_events, EventSpy, CheatSpan, start_cheat_caller_address, stop_cheat_caller_address, }; use alexandria_storage::list::{List, ListTrait}; @@ -102,7 +100,7 @@ fn test_set_public_sale_open_with_owner_role() { let (minter_address, _) = deploy_minter(project_address, erc20_address); // [Prank] Use owner as caller to Minter contract - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -118,42 +116,32 @@ fn test_public_buy() { let (project_address, _) = deploy_project(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract - project.grant_minter_role(minter_address); + + start_cheat_caller_address(project_address, owner_address); + let project_contract = IProjectDispatcher { contract_address: project_address }; + project_contract.grant_minter_role(minter_address); let times: Span = get_mock_times(); let absorptions: Span = get_mock_absorptions(); + let project_carbon: u128 = 8000000000; - setup_project(project_address, 8000000000, times, absorptions,); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - + setup_project(project_address, project_carbon, times, absorptions,); + stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; - // [Assert] project_carbon set correctly - let sale_open = minter.is_public_sale_open(); - assert(sale_open == true, 'public sale not open'); - /// [Check] remaining money to buy in Minter - let max_value: u256 = 8000000000; let remaining_money = minter.get_available_money_amount(); - assert(remaining_money == max_value, 'remaining money wrong value'); + assert(remaining_money == project_carbon.into(), 'remaining money wrong value'); - /// [Approval] approve the minter to spend the money let amount_to_buy: u256 = 1000000000; - // approve the minter to spend the money - start_prank(CheatTarget::One(erc20_address), owner_address); + start_cheat_caller_address(erc20_address, owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; erc20.transfer(user_address, amount_to_buy); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, amount_to_buy); - // [Prank] Use user as caller to Minter and ERC20 contracts - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); - + + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(erc20_address, minter_address); let tokenized_cc: Span = minter.public_buy(amount_to_buy, false); assert(tokenized_cc.len() == 19, 'should be 19 vintages'); } @@ -167,54 +155,38 @@ fn test_get_available_money_amount() { let (project_address, _) = deploy_project(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project and Minter contracts - start_prank(CheatTarget::One(project_address), owner_address); + + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); let times: Span = get_mock_times(); let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values + setup_project(project_address, 8000000000, times, absorptions,); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); + stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; - - // Ensure the public sale is open - let sale_open = minter.is_public_sale_open(); - assert(sale_open == true, 'public sale not open'); - - // Default initial amount of money = 8000000000 let initial_money: u256 = 8000000000; - // Verify if the initial value is correct let remaining_money = minter.get_available_money_amount(); assert(remaining_money == initial_money, 'remaining money wrong value'); let amount_to_buy: u256 = 1000; - // Approve the minter to spend the money and execute a public buy - start_prank(CheatTarget::One(erc20_address), owner_address); + start_cheat_caller_address(erc20_address, owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; erc20.transfer(user_address, amount_to_buy); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, amount_to_buy); - // [Prank] Use user as caller to Minter contract and Minter as caller to ERC20 contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); - + + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(amount_to_buy, false); - stop_prank(CheatTarget::One(minter_address)); - stop_prank(CheatTarget::One(erc20_address)); - - // Test after the buy + stop_cheat_caller_address(minter_address); + stop_cheat_caller_address(erc20_address); + let remaining_money_after_buy = minter.get_available_money_amount(); assert( remaining_money_after_buy == initial_money - amount_to_buy, 'remaining money wrong value' @@ -222,17 +194,15 @@ fn test_get_available_money_amount() { // Buy all the remaining money let remaining_money_to_buy = remaining_money_after_buy; - start_prank(CheatTarget::One(erc20_address), owner_address); + start_cheat_caller_address(erc20_address, owner_address); erc20.transfer(user_address, remaining_money_to_buy); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, remaining_money_to_buy); - // [Prank] Use user as caller to Minter contract and Minter as caller to ERC20 contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(remaining_money_to_buy, false); - - // Test after buying all the remaining money + let remaining_money_after_buying_all = minter.get_available_money_amount(); assert(remaining_money_after_buying_all == 0, 'remaining money wrong value'); } @@ -248,9 +218,8 @@ fn test_cancel_mint() { let minter = IMintDispatcher { contract_address: minter_address }; - // [Prank] Use owner as caller to Minter contract - start_prank(CheatTarget::One(minter_address), owner_address); - + start_cheat_caller_address(minter_address, owner_address); + // Ensure the mint is not canceled initially let is_canceled = minter.is_canceled(); assert(!is_canceled, 'mint should not be canceled'); @@ -278,9 +247,7 @@ fn test_set_unit_price_without_owner_role() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let minter = IMintDispatcher { contract_address: minter_address }; - let price: u256 = 100; - minter.set_unit_price(price); } @@ -291,91 +258,44 @@ fn test_set_unit_price_with_owner_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Minter contract - start_prank(CheatTarget::One(minter_address), owner_address); - + start_cheat_caller_address(minter_address, owner_address); + let minter = IMintDispatcher { contract_address: minter_address }; - let price: u256 = 100; - minter.set_unit_price(price); } #[test] fn test_get_max_money_amount() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project and Minter contracts - start_prank(CheatTarget::One(project_address), owner_address); + + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); + stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; - - // Ensure the public sale is open - let sale_open = minter.is_public_sale_open(); - assert(sale_open == true, 'public sale not open'); - // Default initial max amount of money = 8000000000 let initial_max_money: u256 = 8000000000; - // Verify if the initial max value is correct let max_money = minter.get_max_money_amount(); assert(max_money == initial_max_money, 'max money amount is incorrect'); let amount_to_buy: u256 = 1000; + start_cheat_caller_address(erc20_address, owner_address); - // Approve the minter to spend the money and execute a public buy - start_prank(CheatTarget::One(erc20_address), owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; - erc20.transfer(user_address, amount_to_buy); - - start_prank(CheatTarget::One(erc20_address), user_address); erc20.approve(minter_address, amount_to_buy); - // [Prank] Use user as caller to Minter contract and Minter as caller to ERC20 contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); + start_cheat_caller_address(minter_address, owner_address); + start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(amount_to_buy, false); - stop_prank(CheatTarget::One(minter_address)); - stop_prank(CheatTarget::One(erc20_address)); - - // Test after the buy - let remaining_money_after_buy = minter.get_available_money_amount(); - let current_max_money = initial_max_money - amount_to_buy; - assert(remaining_money_after_buy == current_max_money, 'remaining money is incorrect'); - - // Buy all the remaining money - let remaining_money_to_buy = remaining_money_after_buy; - start_prank(CheatTarget::One(erc20_address), owner_address); - erc20.transfer(user_address, remaining_money_to_buy); - - start_prank(CheatTarget::One(erc20_address), user_address); - erc20.approve(minter_address, remaining_money_to_buy); - // [Prank] Use user as caller to Minter contract and Minter as caller to ERC20 contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); - minter.public_buy(remaining_money_to_buy, false); - - // Test after buying all the remaining money - let remaining_money_after_buying_all = minter.get_available_money_amount(); - assert(remaining_money_after_buying_all == 0, 'remaining money is incorrect'); - + stop_cheat_caller_address(minter_address); + stop_cheat_caller_address(erc20_address); + // Verify the max money amount remains unchanged let max_money_after_buying_all = minter.get_max_money_amount(); assert(max_money_after_buying_all == initial_max_money, 'max money is incorrect'); @@ -385,60 +305,33 @@ fn test_get_max_money_amount() { fn test_get_min_money_amount_per_tx() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project and Minter contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(minter_address), user_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); + stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; - - // Ensure the public sale is open - let sale_open = minter.is_public_sale_open(); - assert(sale_open == true, 'public sale not open'); - - // Default initial min amount of money per transaction = 0 - let initial_min_money_per_tx: u256 = 0; - - // Verify if the initial min value is correct + let initial_min_money_per_tx: u256 = 0; // default value let min_money_per_tx = minter.get_min_money_amount_per_tx(); assert!(min_money_per_tx == initial_min_money_per_tx, "initial min money per tx is incorrect"); let amount_to_buy: u256 = 1000; - - // Approve the minter to spend the money and execute a public buy - start_prank(CheatTarget::One(erc20_address), owner_address); + start_cheat_caller_address(erc20_address, owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; erc20.transfer(user_address, amount_to_buy); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, amount_to_buy); - // [Prank] Use user as caller to Minter contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(amount_to_buy, false); - // Test after the buy - let remaining_money_after_buy = minter.get_available_money_amount(); - assert(remaining_money_after_buy == 8000000000 - amount_to_buy, 'remaining money is incorrect'); - // Verify the min money amount per transaction remains unchanged let min_money_per_tx_after_buy = minter.get_min_money_amount_per_tx(); assert!( @@ -451,57 +344,34 @@ fn test_get_min_money_amount_per_tx() { fn test_is_sold_out() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); + + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); + stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; - - // Ensure the public sale is open - let sale_open = minter.is_public_sale_open(); - assert(sale_open == true, 'public sale not open'); - - // Verify that the contract is not sold out initially let is_sold_out_initial = minter.is_sold_out(); assert(!is_sold_out_initial, 'should not be sold out'); - - // Default initial amount of money = 8000000000 - let initial_money: u256 = 8000000000; - - // Buy all the remaining money - start_prank(CheatTarget::One(erc20_address), owner_address); + + let remaining_money = minter.get_available_money_amount(); + start_cheat_caller_address(erc20_address, owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; - erc20.transfer(user_address, initial_money); + erc20.transfer(user_address, remaining_money); - start_prank(CheatTarget::One(erc20_address), user_address); - erc20.approve(minter_address, initial_money); + start_cheat_caller_address(erc20_address, user_address); + erc20.approve(minter_address, remaining_money); - // [Prank] Use user as caller to Minter contract - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(erc20_address), minter_address); - minter.public_buy(initial_money, false); + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(erc20_address, minter_address); + minter.public_buy(remaining_money, false); - // Test after buying all the remaining money let remaining_money_after_buying_all = minter.get_available_money_amount(); assert(remaining_money_after_buying_all == 0, 'remaining money wrong'); - // Verify that the contract is sold out after buying all the money let is_sold_out_after = minter.is_sold_out(); assert(is_sold_out_after, 'should be sold out'); } @@ -510,32 +380,18 @@ fn test_is_sold_out() { fn test_set_min_money_amount_per_tx() { // Deploy required contracts let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project and Minter contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(minter_address), owner_address); - let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract - project_contract.grant_minter_role(minter_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - // Start testing environment setup - // [Prank] Use owner as caller to ERC20 contract - start_prank(CheatTarget::One(erc20_address), owner_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; - // Verify that the min money amount per tx is 0 at the beginning let min_money_amount_per_tx = minter.get_min_money_amount_per_tx(); assert(min_money_amount_per_tx == 0, 'Initial min per tx incorrect'); - // Test: setting a new valid min money amount per tx let new_min_money_amount: u256 = 500; minter.set_min_money_amount_per_tx(new_min_money_amount); let updated_min_money_amount_per_tx = minter.get_min_money_amount_per_tx(); @@ -550,43 +406,29 @@ fn test_set_min_money_amount_per_tx_without_owner_role() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let minter = IMintDispatcher { contract_address: minter_address }; - let amount: u256 = 100; - minter.set_min_money_amount_per_tx(amount); } #[test] -#[should_panic] +#[should_panic(expected: 'Invalid min money amount per tx')] fn test_set_min_money_amount_per_tx_panic() { // Deploy required contracts let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project and Minter contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - // Start testing environment setup - // [Prank] Use owner as caller to ERC20 contract - start_prank(CheatTarget::One(erc20_address), owner_address); - + + start_cheat_caller_address(erc20_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; - // Verify that the min money amount per tx was set correctly let min_money_amount_per_tx = minter.get_min_money_amount_per_tx(); assert(min_money_amount_per_tx == 0, 'Initial min per tx incorrect'); - // Test: setting a new invalid min money amount per tx (should panic) let new_min_money_amount: u256 = 9999999999; minter.set_min_money_amount_per_tx(new_min_money_amount); } @@ -596,24 +438,12 @@ fn test_set_min_money_amount_per_tx_panic() { #[test] fn test_get_carbonable_project_address() { let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(minter_address), user_address); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); - + start_cheat_caller_address(minter_address, user_address); let minter = IMintDispatcher { contract_address: minter_address }; - - // Ensure the carbonable project address is correct let carbonable_project_address = minter.get_carbonable_project_address(); assert(carbonable_project_address == project_address, 'address does not match'); } @@ -623,24 +453,13 @@ fn test_get_carbonable_project_address() { #[test] fn test_get_payment_token_address() { let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(minter_address), user_address); - - // TODO: check if needed: - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); - + start_cheat_caller_address(minter_address, user_address); let minter = IMintDispatcher { contract_address: minter_address }; - // Ensure the payment token address is correct let payment_token_address = minter.get_payment_token_address(); assert(payment_token_address == erc20_address, 'address does not match'); } @@ -650,22 +469,12 @@ fn test_get_payment_token_address() { #[test] fn test_set_unit_price() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - // Start testing environment setup - start_prank(CheatTarget::One(erc20_address), owner_address); - start_prank(CheatTarget::One(minter_address), owner_address); - - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); - + start_cheat_caller_address(erc20_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; // Ensure the unit price is not set initially @@ -674,19 +483,18 @@ fn test_set_unit_price() { // Set the unit price let new_unit_price: u256 = 1000; - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); minter.set_unit_price(new_unit_price); - stop_prank(CheatTarget::One(minter_address)); + stop_cheat_caller_address(minter_address); - // Verify that the unit price is set correctly let unit_price_after = minter.get_unit_price(); assert(unit_price_after == new_unit_price, 'unit price wrong value'); // Set the unit price to a large value let new_unit_price_large: u256 = 1000000000; - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); minter.set_unit_price(new_unit_price_large); - stop_prank(CheatTarget::One(minter_address)); + stop_cheat_caller_address(minter_address); // Verify that the unit price is set correctly let unit_price_after_large = minter.get_unit_price(); @@ -699,37 +507,24 @@ fn test_set_unit_price() { fn test_get_unit_price() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let user_address: ContractAddress = contract_address_const::<'USER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - // Start testing environment setup - start_prank(CheatTarget::One(minter_address), user_address); - - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); - + + start_cheat_caller_address(minter_address, user_address); let minter = IMintDispatcher { contract_address: minter_address }; - // Ensure the unit price is not set initially let unit_price = minter.get_unit_price(); assert(unit_price == 11, 'unit price should be 11'); - stop_prank(CheatTarget::One(minter_address)); + stop_cheat_caller_address(minter_address); - // Set the unit price - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); let new_unit_price: u256 = 1000; - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); minter.set_unit_price(new_unit_price); - stop_prank(CheatTarget::One(minter_address)); + stop_cheat_caller_address(minter_address); - // Verify that the unit price is set correctly - start_prank(CheatTarget::One(minter_address), user_address); + start_cheat_caller_address(minter_address, user_address); let unit_price_after = minter.get_unit_price(); assert(unit_price_after == new_unit_price, 'unit price wrong value'); } @@ -737,24 +532,14 @@ fn test_get_unit_price() { // set_unit_price_to_zero_panic #[test] -#[should_panic] +#[should_panic(expected: 'Invalid unit price')] fn test_set_unit_price_to_zero_panic() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let (project_address, _) = deploy_project(); + let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - // Start testing environment setup - start_prank(CheatTarget::One(erc20_address), owner_address); - - // let project = IVintageDispatcher { contract_address: project_address }; - // assert(project.is_setup(), 'Error during setup'); - + + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; // Ensure the unit price is not set initially From a752208f3488a50b603fecf13ddf7b2704ac991e Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:14:31 +0200 Subject: [PATCH 3/9] update snfoundry + starknet versions --- tests/test_mint.cairo | 108 +++++++--------- tests/test_offsetter.cairo | 172 +++++++------------------ tests/test_project.cairo | 253 ++++++++++--------------------------- tests/tests_lib.cairo | 50 ++------ 4 files changed, 166 insertions(+), 417 deletions(-) diff --git a/tests/test_mint.cairo b/tests/test_mint.cairo index c3738ca..8dd69f2 100644 --- a/tests/test_mint.cairo +++ b/tests/test_mint.cairo @@ -13,7 +13,8 @@ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTr use snforge_std as snf; use snforge_std::{ - ContractClassTrait, test_address, spy_events, EventSpy, CheatSpan, start_cheat_caller_address, stop_cheat_caller_address, + ContractClassTrait, test_address, spy_events, EventSpy, CheatSpan, start_cheat_caller_address, + stop_cheat_caller_address, }; use alexandria_storage::list::{List, ListTrait}; @@ -39,7 +40,7 @@ use carbon_v3::mock::usdcarb::USDCarb; // Utils for testing purposes use super::tests_lib::{ - get_mock_times, get_mock_absorptions, equals_with_error, deploy_project, setup_project, + get_mock_absorptions, equals_with_error, deploy_project, setup_project, default_setup_and_deploy, deploy_offsetter, deploy_erc20, deploy_minter, buy_utils }; @@ -75,7 +76,6 @@ fn test_is_public_sale_open() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let minter = IMintDispatcher { contract_address: minter_address }; - // [Assert] project_carbon set correctly let sale_open = minter.is_public_sale_open(); assert(sale_open == true, 'public sale not open'); } @@ -121,11 +121,10 @@ fn test_public_buy() { let project_contract = IProjectDispatcher { contract_address: project_address }; project_contract.grant_minter_role(minter_address); - let times: Span = get_mock_times(); let absorptions: Span = get_mock_absorptions(); let project_carbon: u128 = 8000000000; - setup_project(project_address, project_carbon, times, absorptions,); + setup_project(project_address, project_carbon, absorptions); stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -139,7 +138,7 @@ fn test_public_buy() { start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, amount_to_buy); - + start_cheat_caller_address(minter_address, user_address); start_cheat_caller_address(erc20_address, minter_address); let tokenized_cc: Span = minter.public_buy(amount_to_buy, false); @@ -155,15 +154,14 @@ fn test_get_available_money_amount() { let (project_address, _) = deploy_project(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; project_contract.grant_minter_role(minter_address); - let times: Span = get_mock_times(); let absorptions: Span = get_mock_absorptions(); - - setup_project(project_address, 8000000000, times, absorptions,); + + setup_project(project_address, 8000000000, absorptions); stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -180,13 +178,13 @@ fn test_get_available_money_amount() { start_cheat_caller_address(erc20_address, user_address); erc20.approve(minter_address, amount_to_buy); - + start_cheat_caller_address(minter_address, user_address); start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(amount_to_buy, false); stop_cheat_caller_address(minter_address); stop_cheat_caller_address(erc20_address); - + let remaining_money_after_buy = minter.get_available_money_amount(); assert( remaining_money_after_buy == initial_money - amount_to_buy, 'remaining money wrong value' @@ -202,7 +200,7 @@ fn test_get_available_money_amount() { start_cheat_caller_address(minter_address, user_address); start_cheat_caller_address(erc20_address, minter_address); minter.public_buy(remaining_money_to_buy, false); - + let remaining_money_after_buying_all = minter.get_available_money_amount(); assert(remaining_money_after_buying_all == 0, 'remaining money wrong value'); } @@ -219,7 +217,7 @@ fn test_cancel_mint() { let minter = IMintDispatcher { contract_address: minter_address }; start_cheat_caller_address(minter_address, owner_address); - + // Ensure the mint is not canceled initially let is_canceled = minter.is_canceled(); assert(!is_canceled, 'mint should not be canceled'); @@ -259,7 +257,7 @@ fn test_set_unit_price_with_owner_role() { let (minter_address, _) = deploy_minter(project_address, erc20_address); start_cheat_caller_address(minter_address, owner_address); - + let minter = IMintDispatcher { contract_address: minter_address }; let price: u256 = 100; minter.set_unit_price(price); @@ -295,7 +293,7 @@ fn test_get_max_money_amount() { minter.public_buy(amount_to_buy, false); stop_cheat_caller_address(minter_address); stop_cheat_caller_address(erc20_address); - + // Verify the max money amount remains unchanged let max_money_after_buying_all = minter.get_max_money_amount(); assert(max_money_after_buying_all == initial_max_money, 'max money is incorrect'); @@ -356,7 +354,7 @@ fn test_is_sold_out() { let minter = IMintDispatcher { contract_address: minter_address }; let is_sold_out_initial = minter.is_sold_out(); assert(!is_sold_out_initial, 'should not be sold out'); - + let remaining_money = minter.get_available_money_amount(); start_cheat_caller_address(erc20_address, owner_address); let erc20 = IERC20Dispatcher { contract_address: erc20_address }; @@ -422,7 +420,7 @@ fn test_set_min_money_amount_per_tx_panic() { start_cheat_caller_address(minter_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; project_contract.grant_minter_role(minter_address); - + start_cheat_caller_address(erc20_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -510,7 +508,7 @@ fn test_get_unit_price() { let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - + start_cheat_caller_address(minter_address, user_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -538,7 +536,7 @@ fn test_set_unit_price_to_zero_panic() { let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -559,30 +557,25 @@ fn test_withdraw() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(erc20_address), owner_address); - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(erc20_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; let minter = IMintDispatcher { contract_address: minter_address }; let erc20 = IERC20Dispatcher { contract_address: erc20_address }; - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); project.grant_minter_role(minter_address); - start_prank(CheatTarget::One(project_address), minter_address); + start_cheat_caller_address(project_address, minter_address); let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, owner_address, minter_address, share); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); buy_utils(owner_address, user_address, minter_address, share); let balance_owner_before_withdraw = erc20.balance_of(owner_address); let balance_to_withdraw = erc20.balance_of(minter_address); - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(minter_address, owner_address); minter.withdraw(); let balance_owner_after = erc20.balance_of(owner_address); @@ -601,25 +594,20 @@ fn test_withdraw_without_owner_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(erc20_address), owner_address); - start_prank(CheatTarget::One(minter_address), owner_address); - + start_cheat_caller_address(erc20_address, owner_address); + start_cheat_caller_address(minter_address, owner_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; let minter = IMintDispatcher { contract_address: minter_address }; - start_prank(CheatTarget::One(project_address), owner_address); project.grant_minter_role(minter_address); - start_prank(CheatTarget::One(project_address), minter_address); + start_cheat_caller_address(project_address, minter_address); let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, owner_address, minter_address, share); - start_prank(CheatTarget::One(erc20_address), user_address); + start_cheat_caller_address(erc20_address, user_address); buy_utils(owner_address, user_address, minter_address, share); + start_cheat_caller_address(minter_address, user_address); minter.withdraw(); } @@ -629,26 +617,21 @@ fn test_retrieve_amount() { let user_address: ContractAddress = contract_address_const::<'USER'>(); let (project_address, _) = deploy_project(); // Deploy erc20 used for the minter, and a second erc20 that isn't used - let contract = snf::declare('USDCarb'); + let contract = snf::declare("USDCarb").expect('Failed to declare contract'); let mut calldata: Array = array![user_address.into(), user_address.into()]; - let erc20_address = contract.deploy(@calldata).unwrap(); + let (erc20_address, _) = contract.deploy(@calldata).expect('Failed to deploy contract'); calldata = array![user_address.into(), user_address.into()]; - let second_erc20_address = contract.deploy(@calldata).unwrap(); + let (second_erc20_address, _) = contract.deploy(@calldata).expect('Failed to deploy contract'); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(second_erc20_address), user_address); - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(second_erc20_address, user_address); + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; let second_er20 = IERC20Dispatcher { contract_address: second_erc20_address }; // Transfering incorrect token to minter second_er20.transfer(minter_address, 1000); - start_prank(CheatTarget::One(second_erc20_address), minter_address); + start_cheat_caller_address(second_erc20_address, minter_address); minter.retrieve_amount(second_erc20_address, owner_address, 1000); let balance_after = second_er20.balance_of(owner_address); assert(balance_after == 1000, 'balance should be the same'); @@ -661,26 +644,21 @@ fn test_retrieve_amount_without_owner_role() { let user_address: ContractAddress = contract_address_const::<'USER'>(); let (project_address, _) = deploy_project(); // Deploy erc20 used for the minter, and a second erc20 that isn't used - let contract = snf::declare('USDCarb'); + let contract = snf::declare("USDCarb").expect('Failed to declare contract'); let mut calldata: Array = array![user_address.into(), user_address.into()]; - let erc20_address = contract.deploy(@calldata).unwrap(); + let (erc20_address, _) = contract.deploy(@calldata).expect('Failed to deploy contract'); calldata = array![user_address.into(), user_address.into()]; - let second_erc20_address = contract.deploy(@calldata).unwrap(); + let (second_erc20_address, _) = contract.deploy(@calldata).expect('Failed to deploy contract'); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); - let absorptions: Span = get_mock_absorptions(); - // Setup the project with initial values - setup_project(project_address, 8000000000, times, absorptions,); - - start_prank(CheatTarget::One(second_erc20_address), user_address); - start_prank(CheatTarget::One(minter_address), owner_address); + start_cheat_caller_address(second_erc20_address, user_address); + start_cheat_caller_address(minter_address, owner_address); let minter = IMintDispatcher { contract_address: minter_address }; let second_er20 = IERC20Dispatcher { contract_address: second_erc20_address }; // Transfering incorrect token to minter second_er20.transfer(minter_address, 1000); - start_prank(CheatTarget::One(minter_address), user_address); - start_prank(CheatTarget::One(second_erc20_address), minter_address); + start_cheat_caller_address(minter_address, user_address); + start_cheat_caller_address(second_erc20_address, minter_address); minter.retrieve_amount(second_erc20_address, user_address, 1000); } diff --git a/tests/test_offsetter.cairo b/tests/test_offsetter.cairo index 2c49c78..163e3df 100644 --- a/tests/test_offsetter.cairo +++ b/tests/test_offsetter.cairo @@ -18,14 +18,13 @@ use starknet::testing::{set_caller_address, set_contract_address}; // External deps -use openzeppelin::tests::utils::constants as c; use openzeppelin::utils::serde::SerializedAppend; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use snforge_std as snf; use snforge_std::{ - CheatTarget, ContractClassTrait, test_address, spy_events, EventSpy, SpyOn, EventAssertions, - start_warp, start_prank, stop_prank + ContractClassTrait, test_address, spy_events, EventSpy, start_cheat_caller_address, + stop_cheat_caller_address }; use alexandria_storage::list::{List, ListTrait}; @@ -85,9 +84,7 @@ fn test_offsetter_init() { let (offsetter_address, _) = deploy_offsetter(project_address); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; - // [Prank] Use owner as caller to Offsetter contract - start_prank(CheatTarget::One(offsetter_address), user_address); - // [Assert] contract is empty + start_cheat_caller_address(offsetter_address, user_address); let token_id: u256 = 1; let carbon_pending = offsetter.get_carbon_retired(token_id); assert(carbon_pending == 0, 'carbon pending should be 0'); @@ -108,31 +105,24 @@ fn test_offsetter_retire_carbon_credits() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let token_id: u256 = 1; - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter contract the Minter role project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter contract the Offsetter role project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, user_address, minter_address, share); let initial_balance = project.balance_of(user_address, token_id); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] try to retire carbon credits let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_carbon_credits(token_id, 100000); @@ -153,24 +143,18 @@ fn test_offsetter_wrong_status() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter contract the Minter role project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter contract the Offsetter role project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let share = 33 * CC_DECIMALS_MULTIPLIER / 100; // 33% buy_utils(owner_address, user_address, minter_address, share); - // [Check] Vintage status is not audited let vintages = IVintageDispatcher { contract_address: project_address }; let token_id: u256 = 1; let status = vintages.get_carbon_vintage(token_id).status; @@ -191,31 +175,23 @@ fn test_retire_carbon_credits_insufficient_credits() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project_contract.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Effect] setup a batch of carbon credits + stop_cheat_caller_address(project_address); let vintages = IVintageDispatcher { contract_address: project_address }; - let share = 33 * CC_DECIMALS_MULTIPLIER / 100; buy_utils(owner_address, user_address, minter_address, share); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] try to retire carbon credits let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; let user_balance = project_contract.balance_of(user_address, token_id); offsetter.retire_carbon_credits(token_id, user_balance + 1); @@ -230,33 +206,25 @@ fn test_retire_carbon_credits_exact_balance() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project_contract.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share = 33 * CC_DECIMALS_MULTIPLIER / 100; buy_utils(owner_address, user_address, minter_address, share); let token_id: u256 = 1; let user_balance = project_contract.balance_of(user_address, token_id); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] try to retire carbon credits let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_carbon_credits(token_id, user_balance); @@ -276,38 +244,28 @@ fn test_retire_carbon_credits_multiple_retirements() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% - buy_utils(owner_address, user_address, minter_address, share); let token_id: u256 = 1; let balance_initial = project.balance_of(user_address, token_id); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] retire carbon credits multiple times let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_carbon_credits(token_id, 50000); offsetter.retire_carbon_credits(token_id, 50000); - // [Assert] check retired carbon credits let carbon_retired = offsetter.get_carbon_retired(token_id); assert(carbon_retired == 100000, 'Error retired carbon credits'); @@ -326,42 +284,32 @@ fn test_retire_list_carbon_credits_valid_inputs() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% - buy_utils(owner_address, user_address, minter_address, share); let vintage_2024_id: u256 = 1; let vintage_2026_id: u256 = 3; let balance_initial_token_id = project.balance_of(user_address, vintage_2024_id); let balance_initial_2026 = project.balance_of(user_address, vintage_2026_id); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.update_vintage_status(vintage_2024_id, CarbonVintageType::Audited.into()); vintages.update_vintage_status(vintage_2026_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] retire list of carbon credits let vintages: Span = array![vintage_2024_id, vintage_2026_id].span(); let carbon_values: Span = array![50000.into(), 50000.into()].span(); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_list_carbon_credits(vintages, carbon_values); - // [Assert] check retired carbon credits let carbon_retired_token_id = offsetter.get_carbon_retired(vintage_2024_id); let carbon_retired_2026 = offsetter.get_carbon_retired(vintage_2026_id); assert(carbon_retired_token_id == 50000, 'Carbon retired value error'); @@ -374,16 +322,14 @@ fn test_retire_list_carbon_credits_valid_inputs() { } #[test] -#[should_panic(expected: ('Inputs cannot be empty',))] +#[should_panic(expected: 'Inputs cannot be empty')] fn test_retire_list_carbon_credits_empty_inputs() { let user_address: ContractAddress = contract_address_const::<'USER'>(); let (project_address, _) = default_setup_and_deploy(); let (offsetter_address, _) = deploy_offsetter(project_address); - // [Prank] Use user as caller to Offsetter contract - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); - // [Effect] try to retire with empty inputs let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_list_carbon_credits(array![].span(), array![].span()); } @@ -396,10 +342,8 @@ fn test_retire_list_carbon_credits_mismatched_lengths() { let (offsetter_address, _) = deploy_offsetter(project_address); let token_id: u256 = 1; - // [Prank] Use owner as caller to Offsetter contract - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); - // [Effect] try to retire with mismatched lengths let vintages: Span = array![token_id, token_id + 1].span(); let carbon_values: Span = array![100000].span(); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; @@ -407,7 +351,7 @@ fn test_retire_list_carbon_credits_mismatched_lengths() { } #[test] -#[should_panic(expected: ('Vintage status is not audited',))] +#[should_panic(expected: 'Vintage status is not audited')] fn test_retire_list_carbon_credits_partial_valid_inputs() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let user_address: ContractAddress = contract_address_const::<'USER'>(); @@ -416,32 +360,24 @@ fn test_retire_list_carbon_credits_partial_valid_inputs() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% - buy_utils(owner_address, user_address, minter_address, share); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); // Do not update 2026 to keep it invalid - // [Effect] retire list of carbon credits let vintages: Span = array![token_id, token_id + 1].span(); let carbon_values: Span = array![50000.into(), 50000.into()].span(); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; @@ -457,40 +393,30 @@ fn test_retire_list_carbon_credits_multiple_same_vintage() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(offsetter_address, user_address); + start_cheat_caller_address(project_address, owner_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% - buy_utils(owner_address, user_address, minter_address, share); let token_id: u256 = 1; let initial_balance = project.balance_of(user_address, token_id); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] retire list of carbon credits with multiple same vintage let vintages: Span = array![token_id, token_id].span(); let carbon_values: Span = array![50000.into(), 50000.into()].span(); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; offsetter.retire_list_carbon_credits(vintages, carbon_values); - // [Assert] check retired carbon credits let carbon_retired = offsetter.get_carbon_retired(token_id); assert(carbon_retired == 100000, 'Error Carbon retired'); @@ -505,9 +431,7 @@ fn test_get_pending_retirement_no_pending() { let (project_address, _) = default_setup_and_deploy(); let (offsetter_address, _) = deploy_offsetter(project_address); - // [Prank] Use owner as caller to Offsetter contract - start_prank(CheatTarget::One(offsetter_address), user_address); - + start_cheat_caller_address(offsetter_address, user_address); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; let token_id: u256 = 1; @@ -524,9 +448,7 @@ fn test_get_carbon_retired_no_retired() { let (project_address, _) = default_setup_and_deploy(); let (offsetter_address, _) = deploy_offsetter(project_address); - // [Prank] Use owner as caller to Offsetter contract - start_prank(CheatTarget::One(offsetter_address), user_address); - + start_cheat_caller_address(offsetter_address, user_address); let offsetter = IOffsetHandlerDispatcher { contract_address: offsetter_address }; let token_id: u256 = 1; diff --git a/tests/test_project.cairo b/tests/test_project.cairo index e71943a..4b2d3da 100644 --- a/tests/test_project.cairo +++ b/tests/test_project.cairo @@ -5,12 +5,10 @@ use starknet::{ContractAddress, contract_address_const, get_caller_address}; // External deps -use openzeppelin::tests::utils::constants as c; use openzeppelin::utils::serde::SerializedAppend; use snforge_std as snf; use snforge_std::{ - CheatTarget, ContractClassTrait, EventSpy, SpyOn, start_prank, stop_prank, - cheatcodes::events::EventAssertions + ContractClassTrait, EventSpy, start_cheat_caller_address, stop_cheat_caller_address, spy_events }; use alexandria_storage::list::{List, ListTrait}; @@ -51,20 +49,6 @@ fn test_constructor_ok() { let (_project_address, _spy) = deploy_project(); } -#[test] -fn test_is_setup() { - let (project_address, _) = deploy_project(); - // let project = IVintageDispatcher { contract_address: project_address }; - - setup_project( - project_address, - 1573000000, - array![1706785200, 2306401200].span(), - array![0, 1573000000].span(), - ); -// assert(project.is_setup(), 'Error during setup'); -} - #[test] fn test_project_mint() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); @@ -73,17 +57,11 @@ fn test_project_mint() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let vintages = IVintageDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); + stop_cheat_caller_address(project_address); + start_cheat_caller_address(project_address, minter_address); let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% of the total supply let token_id: u256 = 1; @@ -103,12 +81,8 @@ fn test_project_mint_without_minter_role() { let (project_address, _) = default_setup_and_deploy(); let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // let vintages = IVintageDispatcher { contract_address: project_address }; - - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, minter_address); let project_contract = IProjectDispatcher { contract_address: project_address }; let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% of the total supply @@ -117,16 +91,13 @@ fn test_project_mint_without_minter_role() { } #[test] -#[should_panic(expected: ('Only Minter can batch mint',))] +#[should_panic(expected: 'Only Minter can batch mint')] fn test_project_batch_mint_without_minter_role() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let (project_address, _) = default_setup_and_deploy(); let vintages = IVintageDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% of the total supply @@ -163,17 +134,11 @@ fn test_project_batch_mint_with_minter_role() { let (minter_address, _) = deploy_minter(project_address, erc20_address); let vintages = IVintageDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - - // assert(vintage.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); let project_contract = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project_contract.grant_minter_role(minter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); + stop_cheat_caller_address(project_address); + start_cheat_caller_address(project_address, minter_address); let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% of the total supply let num_vintages = vintages.get_num_vintages(); @@ -210,37 +175,26 @@ fn test_project_offset_with_offsetter_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(offsetter_address, user_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); + stop_cheat_caller_address(project_address); + start_cheat_caller_address(project_address, minter_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, user_address, minter_address, share); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Prank] Simulate production flow, Offsetter calls Project contract - start_prank(CheatTarget::One(project_address), offsetter_address); - // [Effect] offset tokens + start_cheat_caller_address(project_address, offsetter_address); project.offset(user_address, token_id, 100); } @@ -254,31 +208,23 @@ fn test_project_offset_without_offsetter_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(offsetter_address, user_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, user_address, minter_address, share); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Prank] Simulate error flow, owner calls Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] offset tokens + start_cheat_caller_address(project_address, owner_address); project.offset(user_address, token_id, 100); } @@ -291,33 +237,24 @@ fn test_project_batch_offset_with_offsetter_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(offsetter_address, user_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Effect] Grant Offsetter role to Offsetter contract project.grant_offsetter_role(offsetter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); + stop_cheat_caller_address(project_address); + start_cheat_caller_address(project_address, minter_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, user_address, minter_address, share); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); let share = 100; let num_vintages = vintages.get_num_vintages(); @@ -336,9 +273,7 @@ fn test_project_batch_offset_with_offsetter_role() { let cc_distribution = cc_distribution.span(); let token_ids = tokens.span(); - // [Prank] Simulate production flow, Offsetter calls Project contract - start_prank(CheatTarget::One(project_address), offsetter_address); - // [Effect] offset tokens + start_cheat_caller_address(project_address, offsetter_address); project.batch_offset(user_address, token_ids, cc_distribution); } @@ -352,30 +287,23 @@ fn test_project_batch_offset_without_offsetter_role() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project, Offsetter, Minter and ERC20 contracts - start_prank(CheatTarget::One(project_address), owner_address); - start_prank(CheatTarget::One(offsetter_address), user_address); + start_cheat_caller_address(project_address, owner_address); + start_cheat_caller_address(offsetter_address, user_address); let project = IProjectDispatcher { contract_address: project_address }; - // [Effect] Grant Minter role to Minter contract project.grant_minter_role(minter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] setup a batch of carbon credits let vintages = IVintageDispatcher { contract_address: project_address }; - let share: u256 = 10 * CC_DECIMALS_MULTIPLIER / 100; // 10% buy_utils(owner_address, user_address, minter_address, share); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - // [Effect] update Vintage status - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, CarbonVintageType::Audited.into()); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); let share = 100; let num_vintages = vintages.get_num_vintages(); @@ -394,9 +322,7 @@ fn test_project_batch_offset_without_offsetter_role() { let cc_distribution = cc_distribution.span(); let token_ids = tokens.span(); - // [Prank] Simulate error flow, owner calls Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] offset tokens + start_cheat_caller_address(project_address, owner_address); project.batch_offset(user_address, token_ids, cc_distribution); } @@ -406,9 +332,7 @@ fn test_project_set_vintage_status() { let (project_address, _) = default_setup_and_deploy(); let vintages = IVintageDispatcher { contract_address: project_address }; - start_prank(CheatTarget::One(project_address), owner_address); - - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); let token_id: u256 = 1; vintages.update_vintage_status(token_id, 3); let vintage: CarbonVintage = vintages.get_carbon_vintage(token_id); @@ -426,16 +350,11 @@ fn test_project_balance_of() { let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] Grant Minter role to Minter contract + start_cheat_caller_address(project_address, owner_address); project_contract.grant_minter_role(minter_address); - // assert(vintages.is_setup(), 'Error during setup'); - let share = 33 * CC_DECIMALS_MULTIPLIER / 100; // 33% of the total supply - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); buy_utils(owner_address, user_address, minter_address, share); let token_id: u256 = 1; let supply_vintage_token_id = vintages.get_carbon_vintage(token_id).supply; @@ -445,7 +364,6 @@ fn test_project_balance_of() { assert(equals_with_error(balance, expected_balance, 10), 'Error of balance'); } - #[test] fn test_transfer_without_loss() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); @@ -455,21 +373,14 @@ fn test_transfer_without_loss() { let project_contract = IProjectDispatcher { contract_address: project_address }; let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] Grant Minter role to Minter contract + start_cheat_caller_address(project_address, owner_address); project_contract.grant_minter_role(minter_address); - // assert(vintages.is_setup(), 'Error during setup'); - let share = 33 * CC_DECIMALS_MULTIPLIER / 100; // 33% of the total supply - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); buy_utils(owner_address, user_address, minter_address, share); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, user calls Project contract - start_prank(CheatTarget::One(project_address), user_address); + stop_cheat_caller_address(project_address); + start_cheat_caller_address(project_address, user_address); let token_id: u256 = 1; let supply_vintage_token_id = vintages.get_carbon_vintage(token_id).supply; let expected_balance = supply_vintage_token_id.into() * share / CC_DECIMALS_MULTIPLIER; @@ -507,13 +418,9 @@ fn test_consecutive_transfers_and_rebases( let vintages = IVintageDispatcher { contract_address: project_address }; let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] Grant Minter role to Minter contract + start_cheat_caller_address(project_address, owner_address); project_contract.grant_minter_role(minter_address); - // assert(vintages.is_setup(), 'Error during setup'); - // Format fuzzing parameters, percentages with 6 digits after the comma, max 299.999999% let DECIMALS_FACTORS = 100_000; let first_percentage_rebase = first_percentage_rebase % 3 * DECIMALS_FACTORS; @@ -529,15 +436,13 @@ fn test_consecutive_transfers_and_rebases( / second_percentage_rebase; let share = 33 * CC_DECIMALS_MULTIPLIER / 100; // 33% of the total supply - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); buy_utils(owner_address, user_address, minter_address, share); let token_id: u256 = 1; let initial_balance = project_contract.balance_of(user_address, token_id); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); // [Prank] Simulate production flow, owner calls Project contract - start_prank(CheatTarget::One(project_address), user_address); + start_cheat_caller_address(project_address, user_address); let receiver_address: ContractAddress = contract_address_const::<'receiver'>(); project_contract @@ -549,24 +454,24 @@ fn test_consecutive_transfers_and_rebases( let new_vintage_supply_1 = initial_vintage_supply * first_percentage_rebase.try_into().unwrap() / 100_000; - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.rebase_vintage(token_id, new_vintage_supply_1); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); let balance_receiver = project_contract.balance_of(receiver_address, token_id); - start_prank(CheatTarget::One(project_address), receiver_address); + start_cheat_caller_address(project_address, receiver_address); project_contract .safe_transfer_from( receiver_address, user_address, token_id, balance_receiver.into(), array![].span() ); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); let new_vintage_supply_2 = new_vintage_supply_1 * second_percentage_rebase.try_into().unwrap() / 100_000; - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); vintages.rebase_vintage(token_id, new_vintage_supply_2); // revert first rebase with the opposite percentage @@ -581,9 +486,9 @@ fn test_consecutive_transfers_and_rebases( / 100_000; vintages.rebase_vintage(token_id, new_vintage_supply_4); - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); - start_prank(CheatTarget::One(project_address), user_address); + start_cheat_caller_address(project_address, user_address); let balance_user = project_contract.balance_of(user_address, token_id); assert(equals_with_error(balance_user, initial_balance, 10), 'Error final balance owner'); @@ -738,16 +643,16 @@ fn fuzz_test_transfer_high_supply_high_amount( #[test] fn test_project_metadata_update() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - let (project_address, mut spy) = default_setup_and_deploy(); + let (project_address, _) = default_setup_and_deploy(); let vintages = IVintageDispatcher { contract_address: project_address }; let project_contract = IProjectDispatcher { contract_address: project_address }; let erc1155_meta = IERC1155MetadataURIDispatcher { contract_address: project_address }; let base_uri: ByteArray = format!("{}", 'uri'); let mut new_uri: ByteArray = format!("{}", 'new/uri'); - start_prank(CheatTarget::One(project_address), owner_address); + start_cheat_caller_address(project_address, owner_address); - let num_vintages = vintages.get_num_vintages(); + // let num_vintages = vintages.get_num_vintages(); let vintage = 1; assert(erc1155_meta.uri(vintage) == base_uri, 'Wrong base token URI'); @@ -755,26 +660,20 @@ fn test_project_metadata_update() { project_contract.set_uri(new_uri.clone()); assert(erc1155_meta.uri(vintage) == new_uri.clone(), 'Wrong updated token URI'); +//check event emitted +// let expected_batch_metadata_update = BatchMetadataUpdate { +// from_token_id: 0, to_token_id: num_vintages.into() +// }; - //check event emitted - let expected_batch_metadata_update = BatchMetadataUpdate { - from_token_id: 0, to_token_id: num_vintages.into() - }; - - spy - .assert_emitted( - @array![(project_address, Event::BatchMetadataUpdate(expected_batch_metadata_update))] - ) +//todo: check if the event is emitted, do all the events assertions } fn test_set_uri() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let (project_address, _) = default_setup_and_deploy(); let project_contract = IProjectDispatcher { contract_address: project_address }; - // let vintages = IVintageDispatcher { contract_address: project_address }; - start_prank(CheatTarget::One(project_address), owner_address); - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); project_contract.set_uri("test_uri"); let uri = project_contract.get_uri(1); assert_eq!(uri, "test_uri"); @@ -784,10 +683,6 @@ fn test_set_uri() { fn test_decimals() { let (project_address, _) = default_setup_and_deploy(); let project_contract = IProjectDispatcher { contract_address: project_address }; - // let vintages = IVintageDispatcher { contract_address: project_address }; - - // assert(vintages.is_setup(), 'Error during setup'); - let project_decimals = project_contract.decimals(); assert(project_decimals == 8, 'Decimals should be 8'); @@ -798,9 +693,6 @@ fn test_shares_of() { let (project_address, _) = default_setup_and_deploy(); let project_contract = IProjectDispatcher { contract_address: project_address }; - // let vintages = IVintageDispatcher { contract_address: project_address }; - // assert(vintages.is_setup(), 'Error during setup'); - let token_id: u256 = 1; let share_balance = project_contract.shares_of(project_address, token_id); @@ -812,9 +704,6 @@ fn test_is_approved_for_all() { let (project_address, _) = default_setup_and_deploy(); let project_contract = IProjectDispatcher { contract_address: project_address }; - // let vintages = IVintageDispatcher { contract_address: project_address }; - // assert(vintages.is_setup(), 'Error during setup'); - let owner = get_caller_address(); let status = project_contract.is_approved_for_all(owner, project_address); @@ -827,19 +716,13 @@ fn test_set_approval_for_all() { let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); let (project_address, _) = default_setup_and_deploy(); let project_contract = IProjectDispatcher { contract_address: project_address }; - // let vintages = IVintageDispatcher { contract_address: project_address }; - - start_prank(CheatTarget::One(project_address), owner_address); - - // assert(vintages.is_setup(), 'Error during setup'); + start_cheat_caller_address(project_address, owner_address); let owner = get_caller_address(); - let approval: bool = false; project_contract.set_approval_for_all(project_address, approval); let status_now = project_contract.is_approved_for_all(owner, project_address); - assert_eq!(status_now, false); } diff --git a/tests/tests_lib.cairo b/tests/tests_lib.cairo index 76ebb7c..83ea5d5 100644 --- a/tests/tests_lib.cairo +++ b/tests/tests_lib.cairo @@ -6,8 +6,10 @@ use starknet::{ContractAddress, contract_address_const}; use openzeppelin::utils::serde::SerializedAppend; use snforge_std as snf; -use snforge_std::{ContractClassTrait, EventSpy, spy_events, EventSpyTrait, - EventSpyAssertionsTrait, start_cheat_caller_address, stop_cheat_caller_address}; +use snforge_std::{ + ContractClassTrait, EventSpy, spy_events, EventSpyTrait, EventSpyAssertionsTrait, + start_cheat_caller_address, stop_cheat_caller_address +}; use alexandria_storage::list::{List, ListTrait}; // Models @@ -35,33 +37,6 @@ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTr /// Mock Data /// -fn get_mock_times() -> Span { - let times: Span = array![ - // 1674579600, - 1706115600, - 1737738000, - 1769274000, - 1800810000, - 1832346000, - 1863968400, - 1895504400, - 1927040400, - 1958576400, - 1990198800, - 2021734800, - 2053270800, - 2084806800, - 2116429200, - 2147965200, - 2179501200, - 2211037200, - 2242659600, - 2274195600 - ] - .span(); - times -} - fn get_mock_absorptions() -> Span { let absorptions: Span = array![ 0, @@ -142,12 +117,7 @@ fn deploy_project() -> (ContractAddress, EventSpy) { (contract_address, spy) } -fn setup_project( - contract_address: ContractAddress, - project_carbon: u128, - times: Span, - absorptions: Span -) { +fn setup_project(contract_address: ContractAddress, project_carbon: u128, absorptions: Span) { let vintages = IVintageDispatcher { contract_address }; // Fake the owner to call set_absorptions and set_project_carbon which can only be run by owner let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); @@ -159,9 +129,8 @@ fn setup_project( fn default_setup_and_deploy() -> (ContractAddress, EventSpy) { let (project_address, spy) = deploy_project(); - let times: Span = get_mock_times(); let absorptions: Span = get_mock_absorptions(); - setup_project(project_address, 8000000000, times, absorptions,); + setup_project(project_address, 8000000000, absorptions); (project_address, spy) } @@ -224,7 +193,6 @@ fn fuzzing_setup(cc_supply: u128) -> (ContractAddress, ContractAddress, Contract let (erc20_address, _) = deploy_erc20(); let (minter_address, _) = deploy_minter(project_address, erc20_address); - let times: Span = get_mock_times(); // Tests are done on a single vintage, thus the absorptions are the same let absorptions: Span = array![ cc_supply, @@ -249,7 +217,7 @@ fn fuzzing_setup(cc_supply: u128) -> (ContractAddress, ContractAddress, Contract cc_supply ] .span(); - setup_project(project_address, 8000000000, times, absorptions,); + setup_project(project_address, 8000000000, absorptions); (project_address, minter_address, erc20_address, spy) } @@ -270,7 +238,7 @@ fn buy_utils( let amount_to_buy = share_to_buy_amount(minter_address, share); // [Prank] Use owner as caller for the ERC20 contract - start_cheat_caller_address(erc20_address, owner_address); // Owner holds initial supply + start_cheat_caller_address(erc20_address, owner_address); // Owner holds initial supply erc20.transfer(caller_address, amount_to_buy); // [Prank] Use caller address (usually user) as caller for the ERC20 contract @@ -316,14 +284,12 @@ fn perform_fuzzed_transfer( let user_address: ContractAddress = contract_address_const::<'USER'>(); let receiver_address: ContractAddress = contract_address_const::<'receiver'>(); let (project_address, minter_address, _, _) = fuzzing_setup(supply); - // let vintages = IVintageDispatcher { contract_address: project_address }; let project = IProjectDispatcher { contract_address: project_address }; // Setup Roles for the contracts start_cheat_caller_address(project_address, owner_address); project.grant_minter_role(minter_address); start_cheat_caller_address(project_address, minter_address); - // assert(vintages.is_setup(), 'Error during setup'); buy_utils(owner_address, user_address, minter_address, share); start_cheat_caller_address(project_address, user_address); From f487d0558e0cf04194885d028bf5c75a66a39be6 Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:14:45 +0200 Subject: [PATCH 4/9] test set_vintages + update snfoundry + starknet versions --- tests/test_vintage.cairo | 615 ++++++--------------------------------- 1 file changed, 93 insertions(+), 522 deletions(-) diff --git a/tests/test_vintage.cairo b/tests/test_vintage.cairo index e6dbaa1..9880203 100644 --- a/tests/test_vintage.cairo +++ b/tests/test_vintage.cairo @@ -5,13 +5,12 @@ use starknet::get_block_timestamp; // External deps -use openzeppelin::tests::utils::constants as c; use openzeppelin::utils::serde::SerializedAppend; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; use snforge_std as snf; use snforge_std::{ - CheatTarget, ContractClassTrait, test_address, spy_events, EventSpy, SpyOn, EventAssertions, - start_warp, start_prank, stop_prank + ContractClassTrait, test_address, spy_events, EventSpy, start_cheat_caller_address, + stop_cheat_caller_address }; // Components @@ -32,7 +31,7 @@ use carbon_v3::contracts::project::{ // Utils for testing purposes use super::tests_lib::{ - get_mock_times, get_mock_absorptions, equals_with_error, deploy_project, setup_project, + get_mock_absorptions, equals_with_error, deploy_project, setup_project, default_setup_and_deploy, fuzzing_setup, perform_fuzzed_transfer, buy_utils, deploy_offsetter, deploy_minter, deploy_erc20 }; @@ -63,30 +62,28 @@ struct Contracts { #[test] fn test_set_project_carbon() { - let (project_address, mut spy) = deploy_project(); + let (project_address, _) = deploy_project(); let vintages = IVintageDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - start_prank(CheatTarget::One(project_address), owner_address); - // [Assert] project_carbon set correctly + start_cheat_caller_address(project_address, owner_address); vintages.set_project_carbon(PROJECT_CARBON); let fetched_value = vintages.get_project_carbon(); assert(fetched_value == PROJECT_CARBON.into(), 'project_carbon wrong value'); - spy - .assert_emitted( - @array![ - ( - project_address, - VintageComponent::Event::ProjectCarbonUpdate( - VintageComponent::ProjectCarbonUpdate { - old_carbon: 0, new_carbon: fetched_value - } - ) - ) - ] - ); - // found events are removed from the spy after assertion, so the length should be 0 - assert(spy.events.len() == 0, 'number of events should be 0'); +// spy +// .assert_emitted( +// @array![ +// ( +// project_address, +// VintageComponent::Event::ProjectCarbonUpdate( +// VintageComponent::ProjectCarbonUpdate { +// old_carbon: 0, new_carbon: fetched_value +// } +// ) +// ) +// ] +// ); +// // found events are removed from the spy after assertion, so the length should be 0 +// assert(spy.events.len() == 0, 'number of events should be 0'); } #[test] @@ -110,383 +107,17 @@ fn test_get_project_carbon_not_set() { fn test_set_project_carbon_twice() { let (project_address, _) = deploy_project(); let vintages = IVintageDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); - start_prank(CheatTarget::One(project_address), owner_address); - // [Assert] project_carbon set correctly + start_cheat_caller_address(project_address, owner_address); vintages.set_project_carbon(PROJECT_CARBON.into()); let fetched_value = vintages.get_project_carbon(); assert(fetched_value == PROJECT_CARBON.into(), 'project_carbon wrong value'); - // [Assert] project_carbon updated correctly let new_value: u128 = 100; vintages.set_project_carbon(new_value); let fetched_value = vintages.get_project_carbon(); assert(fetched_value == new_value, 'project_carbon did not change'); } -/// TODO: set_vintages - -// #[test] -// fn test_set_absorptions() { -// let (project_address, mut spy) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// let times: Span = array![ -// 1651363200, -// 1659312000, -// 1667260800, -// 1675209600, -// 1682899200, -// 1690848000, -// 1698796800, -// 2598134400 -// ] -// .span(); -// let absorptions: Span = array![ -// 0, 1179750, 2359500, 3539250, 4719000, 6685250, 8651500, 1573000000 -// ] -// .span(); - -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// // [Assert] absorptions & times set correctly -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_absorptions() == absorptions, 'absorptions not set correctly'); -// assert(vintages.get_times() == times, 'times not set correctly'); -// let current_time = get_block_timestamp(); -// spy -// .assert_emitted( -// @array![ -// ( -// project_address, -// VintageComponent::Event::AbsorptionUpdate( -// VintageComponent::AbsorptionUpdate { time: current_time } -// ) -// ) -// ] -// ); -// // found events are removed from the spy after assertion, so the length should be 0 -// assert(spy.events.len() == 0, 'number of events should be 0'); - -// // [Assert] absorptions can be fetched correctly according to time -// // at t = 1651363200 -// start_warp(CheatTarget::One(project_address), 1651363200); -// assert(vintages.get_current_absorption() == 0, 'current absorption not correct'); - -// // at t = 1659312000 -// start_warp(CheatTarget::One(project_address), 1659312000); -// assert(vintages.get_current_absorption() == 1179750, 'current absorption not correct'); -// } - -// #[test] -// #[should_panic(expected: 'Caller does not have role')] -// fn test_set_absorptions_without_owner_role() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// let times: Span = array![ -// 1651363200, -// 1659312000, -// 1667260800, -// 1675209600, -// 1682899200, -// 1690848000, -// 1698796800, -// 2598134400 -// ] -// .span(); -// let absorptions: Span = array![ -// 0, 1179750, 2359500, 3539250, 4719000, 6685250, 8651500, 1573000000 -// ] -// .span(); - -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// #[should_panic(expected: ('Times and absorptions mismatch',))] -// fn test_set_absorptions_revert_length_mismatch() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// // [Assert] reverting when times and absorptions have different lengths -// let times: Span = array![1651363200, 1659312000, 1667260800].span(); // length 3 -// let absorptions: Span = array![0, 1179750].span(); // length 2 -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// #[should_panic(expected: ('Inputs cannot be empty',))] -// fn test_set_absorptions_revert_empty_inputs() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// // [Assert] reverting when times and absorptions are empty arrays -// let times: Span = array![].span(); -// let absorptions: Span = array![].span(); -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// #[should_panic(expected: ('Times not sorted',))] -// fn test_set_absorptions_revert_times_not_sorted() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// // [Assert] reverting when times array is not sorted -// let times: Span = array![1651363200, 1659312000, 1657260800].span(); // not sorted -// let absorptions: Span = array![0, 1179750, 2359500].span(); -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// #[should_panic(expected: 'Times not sorted')] -// fn test_set_absorptions_revert_duplicate_times() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1651363200, 1667260800].span(); // duplicate times -// let absorptions: Span = array![0, 1179750, 2359500].span(); -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// #[should_panic(expected: 'Absorptions not sorted',)] -// fn test_set_absorptions_revert_absorptions_not_sorted() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// // [Assert] reverting when absorptions array is not sorted -// let times: Span = array![1651363200, 1659312000, 1667260800].span(); -// let absorptions: Span = array![0, 2359500, 1179750].span(); // not sorted -// vintages.set_absorptions(times, absorptions); -// } - -// #[test] -// fn test_set_absorptions_exact_one_year_interval() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1609459200, 1640995200, 1672531200] -// .span(); // exactly one year apart -// let absorptions: Span = array![0, 1179750, 2359500].span(); -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_absorptions() == absorptions, 'absorptions not set correctly'); -// assert(vintages.get_times() == times, 'times not set correctly'); -// } - -// #[test] -// fn test_set_absorptions_edge_case_timestamps() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![0, 1, 2, 3, 4, 5, 6, 7].span(); // very small timestamps -// let absorptions: Span = array![ -// 0, 1179750, 2359500, 3539250, 4719000, 5898750, 7078500, 8258250 -// ] -// .span(); -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_absorptions() == absorptions, 'absorptions error'); -// assert(vintages.get_times() == times, 'times error'); -// } - -// #[test] -// fn test_set_absorptions_change_length() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800].span(); -// let absorptions: Span = array![0, 1179750, 2359500].span(); - -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_absorptions() == absorptions, 'absorptions error'); - -// let new_times: Span = array![1675209600, 1682899200].span(); -// let new_absorptions: Span = array![3539250, 4719000].span(); -// vintages.set_absorptions(new_times, new_absorptions); -// let length = vintages.get_absorptions().len(); - -// assert(length == new_absorptions.len(), 'length error'); -// assert(vintages.get_absorptions() == new_absorptions, 'absorptions error'); -// assert(vintages.get_times() == new_times, 'times error'); -// } - -// /// get_absorption - -// #[test] -// fn test_get_absorption_interpolation() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800, 1675209600, 1682899200] -// .span(); -// let absorptions: Span = array![0, 1179750, 2359500, 3539250, 4719000].span(); -// vintages.set_absorptions(times, absorptions); -// // Test midpoints between times for linear interpolation -// let mut i = 0; -// loop { -// let mid_time = (*times.at(i) + *times.at(i + 1)) / 2; -// let expected_absorption = (*absorptions.at(i) + *absorptions.at(i + 1)) / 2; -// let absorption = vintages.get_absorption(mid_time); -// assert( -// absorption > *absorptions.at(i) && absorption < *absorptions.at(i + 1), -// 'Interpolation error' -// ); -// assert(absorption == expected_absorption, 'Absorption value not expected'); -// i += 1; - -// if i >= times.len() - 1 { -// break; -// } -// } -// } - -// #[test] -// fn test_get_current_absorption_extrapolation() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800, 1675209600, 1682899200] -// .span(); -// let absorptions: Span = array![0, 1179750, 2359500, 3539250, 4719000].span(); -// vintages.set_absorptions(times, absorptions); -// // Test time before first absorption -// start_warp(CheatTarget::One(project_address), *times.at(0) - 86000); -// let current_absorption = vintages.get_current_absorption(); -// // [Assert] current_absorption should equal first value for times before first time point -// assert(current_absorption == *absorptions.at(0), 'absorption error'); -// // Test time after last absorption -// start_warp(CheatTarget::One(project_address), *times.at(times.len() - 1) + 86000); -// let current_absorption = vintages.get_current_absorption(); -// // [Assert] current_absorption should equal last value for times after last time point -// assert(current_absorption == *absorptions.at(absorptions.len() - 1), 'absorption error'); -// } - -// /// get_current_absorption - -// #[test] -// fn test_get_current_absorption_not_set() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Assert] absorption is 0 when not set at t = 0 -// let absorption = vintages.get_current_absorption(); -// assert(absorption == 0, 'default absorption should be 0'); -// // [Assert] absorption is 0 when not set after t > 0 -// start_warp(CheatTarget::One(project_address), 86000); -// let absorption = vintages.get_current_absorption(); -// assert(absorption == 0, 'default absorption should be 0'); -// } - -// #[test] -// fn test_current_absorption() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800, 1675209600, 1682899200] -// .span(); -// let absorptions: Span = array![ -// 0, 1179750000000, 2359500000000, 3539250000000, 4719000000000 -// ] -// .span(); -// vintages.set_absorptions(times, absorptions); -// // [Assert] At start, absorption = absorptions[0] -// start_warp(CheatTarget::One(project_address), 0); -// let absorption = vintages.get_current_absorption(); -// assert(absorption == *absorptions.at(0), 'Wrong absorption'); -// // [Assert] After start, absorptions[0] < absorption < absorptions[1] -// start_warp(CheatTarget::One(project_address), *times.at(0) + 86000); -// let absorption = vintages.get_current_absorption(); -// assert(absorption > *absorptions.at(0), 'Wrong absorption'); -// assert(absorption < *absorptions.at(1), 'Wrong absorption'); -// // [Assert] Before end, absorptions[-2] < absorption < absorptions[-1] -// start_warp(CheatTarget::One(project_address), *times.at(times.len() - 1) - 86000); -// let absorption = vintages.get_current_absorption(); -// assert(absorption > *absorptions.at(absorptions.len() - 2), 'Wrong absorption'); -// assert(absorption < *absorptions.at(absorptions.len() - 1), 'Wrong absorption'); -// // [Assert] At end, absorption = absorptions[-1] -// start_warp(CheatTarget::One(project_address), *times.at(times.len() - 1)); -// let absorption = vintages.get_current_absorption(); -// assert(absorption == *absorptions.at(absorptions.len() - 1), 'Wrong absorption'); -// // [Assert] After end, absorption = absorptions[-1] -// start_warp(CheatTarget::One(project_address), *times.at(times.len() - 1) + 86000); -// let absorption = vintages.get_current_absorption(); -// assert(absorption == *absorptions.at(absorptions.len() - 1), 'Wrong absorption'); -// } - -// /// get_final_absorption - -// #[test] -// fn test_get_final_absorption() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800].span(); -// let absorptions: Span = array![0, 1179750, 2359500].span(); -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_final_absorption() == 2359500, 'Final absorption not correct'); -// } - -// #[test] -// fn test_get_final_absorption_no_data() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// assert(vintages.get_final_absorption() == 0, 'Final absorption not correct'); -// } - -// #[test] -// fn test_get_final_absorption_single_value() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200].span(); -// let absorptions: Span = array![1179750].span(); -// vintages.set_absorptions(times, absorptions); -// assert(vintages.get_final_absorption() == 1179750, 'Final absorption not correct'); -// } - -// #[test] -// fn test_get_final_absorption_after_updates() { -// let (project_address, _) = deploy_project(); -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Prank] Use owner as caller to Project contract -// let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); -// start_prank(CheatTarget::One(project_address), owner_address); -// let times: Span = array![1651363200, 1659312000, 1667260800].span(); -// let absorptions: Span = array![1000, 2000, 3000].span(); -// vintages.set_absorptions(times, absorptions); - -// let new_times: Span = array![1675209600, 1682899200].span(); -// let new_absorptions: Span = array![4000, 5000].span(); -// vintages.set_absorptions(new_times, new_absorptions); - -// assert(vintages.get_final_absorption() == 5000, 'Final absorption not correct'); -// } - /// share_to_cc #[test] @@ -629,136 +260,83 @@ fn test_cc_to_share_revert_exceeds_supply() { vintages.cc_to_share(cc_value, token_id); } -/// get_cc_vintages - -// #[test] -// fn test_get_cc_vintages() { -// let (project_address, _) = deploy_project(); -// let times: Span = array![1651363200, 1659312000, 1667260800, 1675209600, 1682899200] -// .span(); - -// let absorptions: Span = array![ -// 0, 1179750000000, 2359500000000, 3739250000000, 5119000000000 -// ] -// .span(); -// setup_project(project_address, 121099000000, times, absorptions); - -// let vintages = IVintageDispatcher { contract_address: project_address }; -// // [Assert] cc_vintages set according to absorptions -// let cc_vintages = vintages.get_cc_vintages(); - -// let starting_year: u64 = vintages.get_starting_year(); -// let mut index = 0; - -// let vintage = cc_vintages.at(index); -// let expected__cc_vintage = CarbonVintage { -// vintage: (starting_year.into() + index.into()), -// supply: *absorptions.at(index), -// failed: 0, -// status: CarbonVintageType::Projected, -// }; -// assert(*vintage == expected__cc_vintage, 'vintage not set correctly'); -// index += 1; -// loop { -// if index == absorptions.len() { -// break; -// } -// let vintage = cc_vintages.at(index); -// let expected__cc_vintage = CarbonVintage { -// vintage: (starting_year.into() + index.into()), -// supply: *absorptions.at(index) - *absorptions.at(index - 1), -// failed: 0, -// status: CarbonVintageType::Projected, -// }; -// assert(*vintage == expected__cc_vintage, 'vintage not set correctly'); -// index += 1; -// }; -// // [Assert] cc_vintages set to default values for non-set absorptions -// loop { -// if index == cc_vintages.len() { -// break; -// } -// let vintage = cc_vintages.at(index); -// let expected__cc_vintage: CarbonVintage = CarbonVintage { -// vintage: (starting_year.into() + index.into()), -// supply: 0, -// failed: 0, -// status: CarbonVintageType::Unset, -// }; -// assert(*vintage == expected__cc_vintage, 'vintage not set correctly'); -// index += 1; -// } -// } -/// get_vintage_years +/// set_vintages -#[test] -fn test_get_vintage_multiple() { - let (project_address, _) = default_setup_and_deploy(); +fn test_set_vintages() { + let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); + let (project_address, _) = deploy_project(); + let yearly_absorptions = get_mock_absorptions(); + start_cheat_caller_address(project_address, owner_address); + + let starting_year = 2024; let vintages = IVintageDispatcher { contract_address: project_address }; - let carbon_vintages = vintages.get_cc_vintages(); - let starting_year = 2024_u32; + vintages.set_vintages(yearly_absorptions, starting_year); - let mut index: usize = 0; + let cc_vintages = vintages.get_cc_vintages(); + let mut index = 0; loop { - if index == carbon_vintages.len() { + if index == cc_vintages.len() { break; } - let year = *carbon_vintages.at(index).year; - assert(year == (starting_year + index.into()).into(), 'Year not set correctly'); + let vintage = cc_vintages.at(index); + let expected__cc_vintage = CarbonVintage { + year: (starting_year + index.into()), + supply: *yearly_absorptions.at(index), + failed: 0, + status: CarbonVintageType::Projected, + }; + assert(*vintage == expected__cc_vintage, 'vintage not set correctly'); + index += 1; + }; + + // [Assert] cc_vintages set to default values for non-set absorptions + loop { + if index == cc_vintages.len() { + break; + } + let vintage = cc_vintages.at(index); + let expected__cc_vintage: CarbonVintage = CarbonVintage { + year: (starting_year.into() + index.into()), + supply: 0, + failed: 0, + status: CarbonVintageType::Unset, + }; + assert(*vintage == expected__cc_vintage, 'vintage not set correctly'); index += 1; } } +#[test] +#[should_panic(expected: 'Caller does not have role')] +fn test_set_vintages_without_owner_role() { + let (project_address, _) = deploy_project(); + let yearly_absorptions = get_mock_absorptions(); + let starting_year = 2024; + let vintages = IVintageDispatcher { contract_address: project_address }; + vintages.set_vintages(yearly_absorptions, starting_year); +} + /// get_carbon_vintage -// #[test] -// fn test_get_carbon_vintage() { -// let (project_address, _) = deploy_project(); - -// let times: Span = array![1651363200, 1659312000, 1667260800, 1675209600, 1682899200] -// .span(); - -// let absorptions: Span = array![ -// 0, 1179750000000, 2359500000000, 3739250000000, 5119000000000 -// ] -// .span(); -// setup_project(project_address, 121099000000, times, absorptions); - -// let vintages = IVintageDispatcher { contract_address: project_address }; - -// let mut index = 0; - -// let cc_vintage = cc_handler -// .get_carbon_vintage((vintages.get_starting_year() + index.into()).into()); -// let expected_cc_vintage = CarbonVintage { -// vintage: (vintages.get_starting_year() + index.into()).into(), -// supply: *absorptions.at(index), -// failed: 0, -// status: CarbonVintageType::Projected, -// }; - -// assert(cc_vintage == expected_cc_vintage, 'cc_vintage not set correctly'); -// index += 1; - -// loop { -// if index == absorptions.len() { -// break; -// } -// let starting_year = vintages.get_starting_year(); -// let cc_vintage = vintages.get_carbon_vintage((starting_year + index.into()).into()); - -// let expected_cc_vintage = CarbonVintage { -// vintage: (starting_year + index.into()).into(), -// supply: *absorptions.at(index) - *absorptions.at(index - 1), -// failed: 0, -// status: CarbonVintageType::Projected, -// }; - -// assert(cc_vintage == expected_cc_vintage, 'cc_vintage not set correctly'); -// index += 1; -// }; -// } +#[test] +fn test_get_carbon_vintage() { + let (project_address, _) = default_setup_and_deploy(); + let vintages = IVintageDispatcher { contract_address: project_address }; + + let cc_vintages = vintages.get_cc_vintages(); + let mut index = 0; + loop { + if index == cc_vintages.len() { + break; + } + let token_id: u256 = index.into(); + let vintage = vintages.get_carbon_vintage(token_id); + let expected_vintage = cc_vintages.at(index); + assert(vintage == *expected_vintage, 'Vintage not fetched correctly'); + index += 1; + }; +} #[test] fn test_get_carbon_vintage_non_existent_token_id() { @@ -821,11 +399,12 @@ fn test_update_vintage_status_invalid() { #[should_panic(expected: 'Caller does not have role')] fn test_update_vintage_status_without_owner_role() { let (project_address, _) = deploy_project(); + let user_address: ContractAddress = contract_address_const::<'USER'>(); let vintages = IVintageDispatcher { contract_address: project_address }; let token_id: u256 = 1; let new_status: u8 = 2; - start_prank(CheatTarget::One(project_address), contract_address_const::<'USER'>()); + start_cheat_caller_address(project_address, user_address); vintages.update_vintage_status(token_id, new_status); } @@ -851,21 +430,14 @@ fn test_rebase_half_supply() { let vintages = IVintageDispatcher { contract_address: project_address }; let project = IProjectDispatcher { contract_address: project_address }; - // [Prank] Use owner as caller to Project contract - start_prank(CheatTarget::One(project_address), owner_address); - // [Effect] Grant Minter role to Minter contract + start_cheat_caller_address(project_address, owner_address); project.grant_minter_role(minter_address); - // [Prank] Stop prank on Project contract - stop_prank(CheatTarget::One(project_address)); - // [Prank] Simulate production flow, Minter calls Project contract - start_prank(CheatTarget::One(project_address), minter_address); + start_cheat_caller_address(project_address, minter_address); let share = 50 * CC_DECIMALS_MULTIPLIER / 100; // 50% - buy_utils(owner_address, user_address, minter_address, share); let num_vintages = vintages.get_num_vintages(); - // Rebase every vintage with half the supply let mut index = 0; loop { @@ -875,12 +447,10 @@ fn test_rebase_half_supply() { let token_id: u256 = index.into(); let old_vintage_supply = vintages.get_carbon_vintage(token_id).supply; let old_cc_balance = project.balance_of(owner_address, token_id); - // rebase - // [Prank] use owner to rebase rebase_vintage - start_prank(CheatTarget::One(project_address), owner_address); + // Rebase + start_cheat_caller_address(project_address, owner_address); vintages.rebase_vintage(token_id, old_vintage_supply / 2); - // [Prank] stop prank on vintages contract - stop_prank(CheatTarget::One(project_address)); + stop_cheat_caller_address(project_address); let new_vintage_supply = vintages.get_carbon_vintage(token_id).supply; let new_cc_balance = project.balance_of(owner_address, token_id); let failed_tokens = vintages.get_carbon_vintage(token_id).failed; @@ -890,3 +460,4 @@ fn test_rebase_half_supply() { index += 1; }; } + From cb8b5099c0445c52b41ea2aea858e94ef54cb839 Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:21:08 +0200 Subject: [PATCH 5/9] Naming yearly absorptions --- tests/test_mint.cairo | 8 ++++---- tests/test_vintage.cairo | 2 +- tests/tests_lib.cairo | 14 ++++++++------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/test_mint.cairo b/tests/test_mint.cairo index 8dd69f2..9ed19d9 100644 --- a/tests/test_mint.cairo +++ b/tests/test_mint.cairo @@ -121,10 +121,10 @@ fn test_public_buy() { let project_contract = IProjectDispatcher { contract_address: project_address }; project_contract.grant_minter_role(minter_address); - let absorptions: Span = get_mock_absorptions(); + let yearly_absorptions: Span = get_mock_absorptions(); let project_carbon: u128 = 8000000000; - setup_project(project_address, project_carbon, absorptions); + setup_project(project_address, project_carbon, yearly_absorptions); stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; @@ -159,9 +159,9 @@ fn test_get_available_money_amount() { let project_contract = IProjectDispatcher { contract_address: project_address }; project_contract.grant_minter_role(minter_address); - let absorptions: Span = get_mock_absorptions(); + let yearly_absorptions: Span = get_mock_absorptions(); - setup_project(project_address, 8000000000, absorptions); + setup_project(project_address, 8000000000, yearly_absorptions); stop_cheat_caller_address(project_address); let minter = IMintDispatcher { contract_address: minter_address }; diff --git a/tests/test_vintage.cairo b/tests/test_vintage.cairo index 9880203..6c1adbb 100644 --- a/tests/test_vintage.cairo +++ b/tests/test_vintage.cairo @@ -290,7 +290,7 @@ fn test_set_vintages() { index += 1; }; - // [Assert] cc_vintages set to default values for non-set absorptions + // [Assert] cc_vintages set to default values for non-set yearly_absorptions loop { if index == cc_vintages.len() { break; diff --git a/tests/tests_lib.cairo b/tests/tests_lib.cairo index 83ea5d5..80527f4 100644 --- a/tests/tests_lib.cairo +++ b/tests/tests_lib.cairo @@ -117,20 +117,22 @@ fn deploy_project() -> (ContractAddress, EventSpy) { (contract_address, spy) } -fn setup_project(contract_address: ContractAddress, project_carbon: u128, absorptions: Span) { +fn setup_project( + contract_address: ContractAddress, project_carbon: u128, yearly_absorptions: Span +) { let vintages = IVintageDispatcher { contract_address }; // Fake the owner to call set_absorptions and set_project_carbon which can only be run by owner let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); start_cheat_caller_address(contract_address, owner_address); - vintages.set_vintages(absorptions, 2024); + vintages.set_vintages(yearly_absorptions, 2024); vintages.set_project_carbon(project_carbon); } fn default_setup_and_deploy() -> (ContractAddress, EventSpy) { let (project_address, spy) = deploy_project(); - let absorptions: Span = get_mock_absorptions(); - setup_project(project_address, 8000000000, absorptions); + let yearly_absorptions: Span = get_mock_absorptions(); + setup_project(project_address, 8000000000, yearly_absorptions); (project_address, spy) } @@ -194,7 +196,7 @@ fn fuzzing_setup(cc_supply: u128) -> (ContractAddress, ContractAddress, Contract let (minter_address, _) = deploy_minter(project_address, erc20_address); // Tests are done on a single vintage, thus the absorptions are the same - let absorptions: Span = array![ + let yearly_absorptions: Span = array![ cc_supply, cc_supply, cc_supply, @@ -217,7 +219,7 @@ fn fuzzing_setup(cc_supply: u128) -> (ContractAddress, ContractAddress, Contract cc_supply ] .span(); - setup_project(project_address, 8000000000, absorptions); + setup_project(project_address, 8000000000, yearly_absorptions); (project_address, minter_address, erc20_address, spy) } From 05c91f3b75526cd0ce53d2790468c1b3f9b93bdc Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:27:38 +0200 Subject: [PATCH 6/9] Update Contributing versioning --- Contributing.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Contributing.md b/Contributing.md index 600fddf..d4c13c2 100644 --- a/Contributing.md +++ b/Contributing.md @@ -23,16 +23,16 @@ If you have an idea for a new feature, please submit a feature request using the #### Requirements -- [Scarb](https://docs.swmansion.com/scarb/): *v2.5.4* -- [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/index.html) *v0.18.0* +- [Scarb](https://docs.swmansion.com/scarb/): *v2.6.0* +- [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/index.html) *v0.26.0* We recommend installing dependencies using [asdf](https://asdf-vm.com/): ```bash asdf plugin add scarb -asdf install scarb 2.5.4 +asdf install scarb 2.6.0 asdf plugin add starknet-foundry -asdf install starknet-foundry 0.18.0 +asdf install starknet-foundry 0.26.0 ``` #### Compile From 02c22823487924c4b3a50e5df615be6901eca728 Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:28:14 +0200 Subject: [PATCH 7/9] CI versioning + tests CI runs when needed --- .github/workflows/build.yml | 2 +- .github/workflows/tests.yml | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03a18ba..630b924 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.5.4" + scarb-version: "2.6.0" - name: Cairo lint run: scarb fmt --check - name: Cairo build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c6e0de1..bdaacd4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,13 +1,15 @@ name: Run Tests on: pull_request: - types: - - closed + branches: + - main + push: + branches: + - main jobs: check: runs-on: ubuntu-latest - if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main' steps: - name: Checkout repository @@ -16,7 +18,7 @@ jobs: - name: Setup Scarb uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.5.4" + scarb-version: "2.6.0" - name: Setup snfoundry uses: foundry-rs/setup-snfoundry@v3 From 90e15bea01d8946943da576a808e216d3d4cbcb1 Mon Sep 17 00:00:00 2001 From: julienbrs Date: Wed, 17 Jul 2024 12:47:21 +0200 Subject: [PATCH 8/9] update Test badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b913d98..bb4a088 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ ## About -[![Tests](https://img.shields.io/badge/Tests-108%20passed-brightgreen)](README.md) +[![Tests](https://img.shields.io/badge/Tests-92%20passed-brightgreen)](README.md) Carbon Protocol V3 is a cutting-edge, open-source tool designed for the tokenization, trading, and management of carbon credits on Starknet. From 9c1cf3d32973c3d41e6cc1e4f2c387072f0ab84f Mon Sep 17 00:00:00 2001 From: julienbrs Date: Mon, 22 Jul 2024 14:48:38 +0200 Subject: [PATCH 9/9] Add .tool-versions --- .gitignore | 1 - .tool-versions | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .tool-versions diff --git a/.gitignore b/.gitignore index 9fed2f0..960aee7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ node.json artifacts target Scarb.lock -.tool-versions # nile 127.0.0.1.* diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..7736380 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +starknet-foundry 0.26.0 +scarb 2.6.0