diff --git a/Scarb.toml b/Scarb.toml index bcd4db3..27a7c21 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -8,6 +8,7 @@ repository = "https://github.com/carbonable-labs/carbon-protocol-v3" keywords = ["starknet", "carbon credits", "carbonable", "protocol"] readme = "README.md" documentation = "https://github.com/carbonable-labs/carbon-protocol-v3" +edition = "2024_07" [dependencies] starknet = ">=2.8.5" diff --git a/src/components/erc1155/erc1155.cairo b/src/components/erc1155/erc1155.cairo index b33c6f6..862dcfe 100644 --- a/src/components/erc1155/erc1155.cairo +++ b/src/components/erc1155/erc1155.cairo @@ -7,6 +7,7 @@ /// See https://eips.ethereum.org/EIPS/eip-1155. #[starknet::component] pub mod ERC1155Component { + use core::num::traits::Zero; use crate::components::erc1155::interface::{ IERC1155ReceiverDispatcher, IERC1155ReceiverDispatcherTrait }; @@ -222,8 +223,8 @@ pub mod ERC1155Component { values: Span, data: Span ) { - assert(Zeroable::is_non_zero(from), Errors::INVALID_SENDER); - assert(Zeroable::is_non_zero(to), Errors::INVALID_RECEIVER); + assert(from.is_non_zero(), Errors::INVALID_SENDER); + assert(to.is_non_zero(), Errors::INVALID_RECEIVER); let operator = get_caller_address(); if from != operator { @@ -496,11 +497,11 @@ pub mod ERC1155Component { value: u256, data: Span ) { - assert(Zeroable::is_non_zero(to), Errors::INVALID_RECEIVER); + assert(to.is_non_zero(), Errors::INVALID_RECEIVER); let token_ids = array![token_id].span(); let values = array![value].span(); - self.update_with_acceptance_check(Zeroable::zero(), to, token_ids, values, data); + self.update_with_acceptance_check(Zero::zero(), to, token_ids, values, data); } /// Batched version of `mint_with_acceptance_check`. @@ -521,8 +522,8 @@ pub mod ERC1155Component { values: Span, data: Span ) { - assert(Zeroable::is_non_zero(to), Errors::INVALID_RECEIVER); - self.update_with_acceptance_check(Zeroable::zero(), to, token_ids, values, data); + assert(to.is_non_zero(), Errors::INVALID_RECEIVER); + self.update_with_acceptance_check(Zero::zero(), to, token_ids, values, data); } /// Destroys a `value` amount of tokens of type `token_id` from `from`. @@ -539,11 +540,11 @@ pub mod ERC1155Component { token_id: u256, value: u256 ) { - assert(Zeroable::is_non_zero(from), Errors::INVALID_SENDER); + assert(from.is_non_zero(), Errors::INVALID_SENDER); let token_ids = array![token_id].span(); let values = array![value].span(); - self.update(from, Zeroable::zero(), token_ids, values); + self.update(from, Zero::zero(), token_ids, values); } /// Batched version of `burn`. @@ -561,8 +562,8 @@ pub mod ERC1155Component { token_ids: Span, values: Span ) { - assert(Zeroable::is_non_zero(from), Errors::INVALID_SENDER); - self.update(from, Zeroable::zero(), token_ids, values); + assert(from.is_non_zero(), Errors::INVALID_SENDER); + self.update(from, Zero::zero(), token_ids, values); } /// Version of `update` that performs the token acceptance check by calling @@ -626,12 +627,12 @@ pub mod ERC1155Component { } let token_id = *token_ids.at(index); let value = *values.at(index); - if Zeroable::is_non_zero(from) { + if from.is_non_zero() { let from_balance = self.ERC1155_balances.read((token_id, from)); assert(from_balance >= value, Errors::INSUFFICIENT_BALANCE); self.ERC1155_balances.write((token_id, from), from_balance - value); } - if Zeroable::is_non_zero(to) { + if to.is_non_zero() { let to_balance = self.ERC1155_balances.read((token_id, to)); self.ERC1155_balances.write((token_id, to), to_balance + value); } @@ -673,7 +674,7 @@ pub mod ERC1155Component { let token_ids = array![token_id].span(); let values = array![value].span(); - self.update(Zeroable::zero(), to, token_ids, values); + self.update(Zero::zero(), to, token_ids, values); } /// Batched version of `mint_with_acceptance_check`. @@ -694,7 +695,7 @@ pub mod ERC1155Component { values: Span ) { assert(to.is_non_zero(), Errors::INVALID_RECEIVER); - self.update(Zeroable::zero(), to, token_ids, values); + self.update(Zero::zero(), to, token_ids, values); } /// Sets a new URI for all token types, by relying on the token type ID diff --git a/src/components/metadata.cairo b/src/components/metadata.cairo index 613fed0..ddebd95 100644 --- a/src/components/metadata.cairo +++ b/src/components/metadata.cairo @@ -1,7 +1,7 @@ use starknet::{ClassHash, ContractAddress}; #[starknet::interface] -trait IMetadataHandler { +pub trait IMetadataHandler { fn uri(self: @TContractState, token_id: u256) -> Span; fn get_provider(self: @TContractState) -> ContractAddress; fn set_provider(ref self: TContractState, provider: ContractAddress); @@ -10,17 +10,18 @@ trait IMetadataHandler { } #[starknet::interface] -trait IMetadataDescriptor { +pub trait IMetadataDescriptor { fn construct_uri(self: @TContractState, token_id: u256) -> Span; } #[starknet::component] -mod MetadataComponent { +pub mod MetadataComponent { + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; use starknet::{ClassHash, ContractAddress}; use super::{IMetadataDescriptorLibraryDispatcher, IMetadataDescriptorDispatcherTrait}; #[storage] - struct Storage { + pub struct Storage { MetadataHandler_uri_implementation: ClassHash, MetadataHandler_provider: ContractAddress, } @@ -60,7 +61,7 @@ mod MetadataComponent { } fn set_uri(ref self: ComponentState, class_hash: ClassHash,) { - assert(!class_hash.is_zero(), 'URI class hash cannot be zero'); + assert(class_hash.into() != 0, 'URI class hash cannot be zero'); let old_class_hash = self.MetadataHandler_uri_implementation.read(); self.MetadataHandler_uri_implementation.write(class_hash); self.emit(MetadataUpgraded { old_class_hash, class_hash }); @@ -70,10 +71,7 @@ mod MetadataComponent { #[cfg(test)] mod TestMetadataComponent { - use starknet::ClassHash; - use super::MetadataComponent; use super::{IMetadataHandlerDispatcherTrait, IMetadataHandlerDispatcher}; - use carbon_v3::mock::metadata::TestMetadata; use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; #[test] diff --git a/src/components/minter/booking.cairo b/src/components/minter/booking.cairo index 1757b4c..699962d 100644 --- a/src/components/minter/booking.cairo +++ b/src/components/minter/booking.cairo @@ -1,7 +1,7 @@ // Core imports #[derive(Drop, Copy)] -enum BookingStatus { +pub enum BookingStatus { Unknown: (), Booked: (), Failed: (), @@ -10,13 +10,13 @@ enum BookingStatus { } #[derive(Drop, Copy, Serde, starknet::Store)] -struct Booking { +pub struct Booking { value: u256, amount: u256, status: u8, } -trait BookingTrait { +pub trait BookingTrait { fn new(value: u256, amount: u256, status: BookingStatus) -> Booking; fn get_status(ref self: Booking) -> BookingStatus; fn set_status(ref self: Booking, status: BookingStatus); diff --git a/src/components/minter/interface.cairo b/src/components/minter/interface.cairo index 4286eaf..d5a18b7 100644 --- a/src/components/minter/interface.cairo +++ b/src/components/minter/interface.cairo @@ -1,7 +1,7 @@ use starknet::ContractAddress; #[starknet::interface] -trait IMint { +pub trait IMint { fn get_carbonable_project_address(self: @TContractState) -> ContractAddress; fn get_payment_token_address(self: @TContractState) -> ContractAddress; fn get_unit_price(self: @TContractState) -> u256; diff --git a/src/components/minter/mint.cairo b/src/components/minter/mint.cairo index e8911ba..04adac7 100644 --- a/src/components/minter/mint.cairo +++ b/src/components/minter/mint.cairo @@ -1,35 +1,30 @@ #[starknet::component] -mod MintComponent { +pub mod MintComponent { // Starknet imports + use core::num::traits::Zero; use starknet::ContractAddress; use starknet::{get_caller_address, get_contract_address}; - use starknet::storage::{ - StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry, Map - }; + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess, Map}; // External imports use openzeppelin::token::erc20::interface::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait}; - use openzeppelin::token::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; // Internal imports use carbon_v3::components::minter::interface::IMint; - use carbon_v3::components::minter::booking::{Booking, BookingStatus, BookingTrait}; use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; use carbon_v3::contracts::project::{ IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; - use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; - use carbon_v3::contracts::project::Project::{OWNER_ROLE}; // Constants - use carbon_v3::models::constants::{MULTIPLIER_TONS_TO_MGRAMS}; + use carbon_v3::constants::{MULTIPLIER_TONS_TO_MGRAMS}; #[storage] - struct Storage { + pub struct Storage { Mint_carbonable_project_address: ContractAddress, Mint_payment_token_address: ContractAddress, Mint_public_sale_open: bool, @@ -43,7 +38,7 @@ mod MintComponent { #[event] #[derive(Drop, starknet::Event)] - enum Event { + pub enum Event { PublicSaleOpen: PublicSaleOpen, PublicSaleClose: PublicSaleClose, SoldOut: SoldOut, @@ -59,81 +54,81 @@ mod MintComponent { } #[derive(Drop, starknet::Event)] - struct PublicSaleOpen { - old_value: bool, - new_value: bool + pub struct PublicSaleOpen { + pub old_value: bool, + pub new_value: bool } #[derive(Drop, starknet::Event)] - struct PublicSaleClose { - old_value: bool, - new_value: bool + pub struct PublicSaleClose { + pub old_value: bool, + pub new_value: bool } #[derive(Drop, starknet::Event)] - struct SoldOut { - sold_out: bool + pub struct SoldOut { + pub sold_out: bool } #[derive(Drop, starknet::Event)] - struct Buy { + pub struct Buy { #[key] - address: ContractAddress, - cc_amount: u256, - vintages: Span, + pub address: ContractAddress, + pub cc_amount: u256, + pub vintages: Span, } #[derive(Drop, starknet::Event)] - struct MintCanceled { - is_canceled: bool + pub struct MintCanceled { + pub is_canceled: bool } #[derive(Drop, starknet::Event)] - struct UnitPriceUpdated { - old_price: u256, - new_price: u256, + pub struct UnitPriceUpdated { + pub old_price: u256, + pub new_price: u256, } #[derive(Drop, starknet::Event)] - struct Withdraw { - recipient: ContractAddress, - amount: u256, + pub struct Withdraw { + pub recipient: ContractAddress, + pub amount: u256, } #[derive(Drop, starknet::Event)] - struct AmountRetrieved { - token_address: ContractAddress, - recipient: ContractAddress, - amount: u256, + pub struct AmountRetrieved { + pub token_address: ContractAddress, + pub recipient: ContractAddress, + pub amount: u256, } #[derive(Drop, starknet::Event)] - struct MinMoneyAmountPerTxUpdated { - old_amount: u256, - new_amount: u256, + pub struct MinMoneyAmountPerTxUpdated { + pub old_amount: u256, + pub new_amount: u256, } #[derive(Drop, starknet::Event)] - struct MaxMintableCCUpdated { - old_value: u256, - new_value: u256, + pub struct MaxMintableCCUpdated { + pub old_value: u256, + pub new_value: u256, } #[derive(Drop, starknet::Event)] - struct RemainingMintableCCUpdated { - old_value: u256, - new_value: u256, + pub struct RemainingMintableCCUpdated { + pub old_value: u256, + pub new_value: u256, } #[derive(Drop, starknet::Event)] - struct RedeemInvestment { - address: ContractAddress, - amount: u256, + pub struct RedeemInvestment { + pub address: ContractAddress, + pub amount: u256, } - mod Errors { - const INVALID_ARRAY_LENGTH: felt252 = 'Mint: invalid array length'; + pub mod Errors { + pub const INVALID_ARRAY_LENGTH: felt252 = 'Mint: invalid array length'; } #[embeddable_as(MintImpl)] @@ -179,7 +174,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -201,7 +196,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -233,7 +228,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -251,7 +246,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); assert(unit_price > 0, 'Invalid unit price'); @@ -267,7 +262,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -292,7 +287,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -314,7 +309,7 @@ mod MintComponent { let vintages = IVintageDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let is_canceled = self.Mint_cancel.read(); assert(is_canceled, 'Mint is not canceled'); @@ -374,7 +369,7 @@ mod MintComponent { let project = IProjectDispatcher { contract_address: project_address }; let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let isOwner = project.only_owner(caller_address); assert(isOwner, 'Caller is not the owner'); @@ -390,7 +385,7 @@ mod MintComponent { } #[generate_trait] - impl InternalImpl< + pub impl InternalImpl< TContractState, +HasComponent, +Drop > of InternalTrait { fn initializer( @@ -414,7 +409,7 @@ mod MintComponent { assert(cc_amount > 0, 'Invalid carbon credit amount'); let caller_address = get_caller_address(); - assert(!caller_address.is_zero(), 'Invalid caller'); + assert(caller_address.is_non_zero(), 'Invalid caller'); let unit_price = self.Mint_unit_price.read(); // If user wants to buy 1 carbon credit, the input should be 1*MULTIPLIER_TONS_TO_MGRAMS diff --git a/src/components/offsetter/interface.cairo b/src/components/offsetter/interface.cairo index c73753b..068a531 100644 --- a/src/components/offsetter/interface.cairo +++ b/src/components/offsetter/interface.cairo @@ -1,8 +1,7 @@ use starknet::ContractAddress; -use carbon_v3::models::carbon_vintage::CarbonVintage; #[starknet::interface] -trait IOffsetHandler { +pub trait IOffsetHandler { /// Deposit carbon credits from one vintage for offset. fn deposit_vintage(ref self: TContractState, token_id: u256, cc_amount: u256); @@ -15,6 +14,7 @@ trait IOffsetHandler { from: ContractAddress, amount: u128, timestamp: u128, + vintage: u256, id: u128, proof: Array:: ) -> bool; @@ -22,7 +22,12 @@ trait IOffsetHandler { ///Verify on the business logic side, confirm on the Merkle tree side, and perform the offset ///action. fn confirm_offset( - ref self: TContractState, amount: u128, timestamp: u128, id: u128, proof: Array:: + ref self: TContractState, + amount: u128, + timestamp: u128, + vintage: u256, + id: u128, + proof: Array:: ); fn get_allocation_id(self: @TContractState, from: ContractAddress) -> u256; @@ -42,6 +47,11 @@ trait IOffsetHandler { fn get_merkle_root(self: @TContractState) -> felt252; fn check_claimed( - self: @TContractState, claimee: ContractAddress, timestamp: u128, amount: u128, id: u128 + self: @TContractState, + claimee: ContractAddress, + timestamp: u128, + amount: u128, + vintage: u256, + id: u128 ) -> bool; } diff --git a/src/components/offsetter/offset_handler.cairo b/src/components/offsetter/offset_handler.cairo index 7959245..f8cd2b4 100644 --- a/src/components/offsetter/offset_handler.cairo +++ b/src/components/offsetter/offset_handler.cairo @@ -13,30 +13,22 @@ pub mod OffsetComponent { // Internal imports use carbon_v3::components::offsetter::interface::IOffsetHandler; - use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; + use carbon_v3::models::{Allocation, CarbonVintage, CarbonVintageType}; use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; use carbon_v3::components::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; use carbon_v3::contracts::project::{ IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; - use carbon_v3::contracts::project::Project::OWNER_ROLE; + use carbon_v3::constants::OWNER_ROLE; use alexandria_merkle_tree::merkle_tree::{ Hasher, MerkleTree, MerkleTreeImpl, pedersen::PedersenHasherImpl, MerkleTreeTrait, }; use openzeppelin::access::accesscontrol::interface::IAccessControl; - #[derive(Copy, Drop, Debug, Hash, starknet::Store, Serde, PartialEq)] - struct Allocation { - claimee: ContractAddress, - amount: u128, - timestamp: u128, - id: u128 - } - #[storage] - struct Storage { + pub struct Storage { Offsetter_carbonable_project_address: ContractAddress, Offsetter_carbon_pending_retirement: Map<(u256, ContractAddress), u256>, Offsetter_carbon_retired: Map<(u256, ContractAddress), u256>, @@ -47,7 +39,7 @@ pub mod OffsetComponent { #[event] #[derive(Drop, starknet::Event)] - enum Event { + pub enum Event { RequestedRetirement: RequestedRetirement, Retired: Retired, PendingRetirementRemoved: PendingRetirementRemoved, @@ -55,39 +47,39 @@ pub mod OffsetComponent { } #[derive(Drop, starknet::Event)] - struct RequestedRetirement { + pub struct RequestedRetirement { #[key] - from: ContractAddress, + pub from: ContractAddress, #[key] - project: ContractAddress, + pub project: ContractAddress, #[key] - token_id: u256, + pub token_id: u256, #[key] - allocation_id: u256, - old_amount: u256, - new_amount: u256 + pub allocation_id: u256, + pub old_amount: u256, + pub new_amount: u256 } #[derive(Drop, starknet::Event)] - struct Retired { + pub struct Retired { #[key] - from: ContractAddress, + pub from: ContractAddress, #[key] - project: ContractAddress, + pub project: ContractAddress, #[key] - token_id: u256, - old_amount: u256, - new_amount: u256 + pub token_id: u256, + pub old_amount: u256, + pub new_amount: u256 } #[derive(Drop, starknet::Event)] - struct PendingRetirementRemoved { + pub struct PendingRetirementRemoved { #[key] - from: ContractAddress, + pub from: ContractAddress, #[key] - token_id: u256, - old_amount: u256, - new_amount: u256 + pub token_id: u256, + pub old_amount: u256, + pub new_amount: u256 } #[derive(Drop, starknet::Event)] @@ -99,16 +91,16 @@ pub mod OffsetComponent { } pub mod Errors { - const INVALID_VINTAGE: felt252 = 'Offset: Invalid vintage'; - const NOT_ENOUGH_CARBON: felt252 = 'Offset: Not enough carbon'; - const NOT_ENOUGH_PENDING: felt252 = 'Offset: Not enough pending'; - const EMPTY_INPUT: felt252 = 'Offset: Inputs cannot be empty'; - const ARRAY_MISMATCH: felt252 = 'Offset: Array length mismatch'; - const INVALID_PROOF: felt252 = 'Offset: Invalid proof'; - const ALREADY_CLAIMED: felt252 = 'Offset: Already claimed'; - const MISSING_ROLE: felt252 = 'Offset: Missing role'; - const ZERO_ADDRESS: felt252 = 'Offset: Address is invalid'; - const INVALID_DEPOSIT: felt252 = 'Offset: Invalid deposit'; + pub const INVALID_VINTAGE: felt252 = 'Offset: Invalid vintage'; + pub const NOT_ENOUGH_CARBON: felt252 = 'Offset: Not enough carbon'; + pub const NOT_ENOUGH_PENDING: felt252 = 'Offset: Not enough pending'; + pub const EMPTY_INPUT: felt252 = 'Offset: Inputs cannot be empty'; + pub const ARRAY_MISMATCH: felt252 = 'Offset: Array length mismatch'; + pub const INVALID_PROOF: felt252 = 'Offset: Invalid proof'; + pub const ALREADY_CLAIMED: felt252 = 'Offset: Already claimed'; + pub const MISSING_ROLE: felt252 = 'Offset: Missing role'; + pub const ZERO_ADDRESS: felt252 = 'Offset: Address is invalid'; + pub const INVALID_DEPOSIT: felt252 = 'Offset: Invalid deposit'; } #[embeddable_as(OffsetHandlerImpl)] @@ -163,9 +155,11 @@ pub mod OffsetComponent { from: ContractAddress, amount: u128, timestamp: u128, + vintage: u256, id: u128, proof: Array:: ) -> bool { + // TODO: add vintage in leaf let mut merkle_tree: MerkleTree = MerkleTreeImpl::new(); // [Verify the proof] @@ -189,25 +183,24 @@ pub mod OffsetComponent { ref self: ComponentState, amount: u128, timestamp: u128, + vintage: u256, id: u128, proof: Array:: ) { let claimee = get_caller_address(); // [Verify not already claimed] - let claimed = self.check_claimed(claimee, timestamp, amount, id); + let claimed = self.check_claimed(claimee, timestamp, amount, vintage, id); assert(!claimed, Errors::ALREADY_CLAIMED); // [Verify if the merkle tree claim is possible] - let _ = self.confirm_for_merkle_tree(claimee, amount, timestamp, id, proof); + let _ = self.confirm_for_merkle_tree(claimee, amount, timestamp, vintage, id, proof); //If everything is correct, we offset the carbon credits self._offset_carbon_credit(claimee, 1, amount.into()); // [Mark as claimed] - let allocation = Allocation { - claimee: claimee, amount: amount, timestamp: timestamp, id: id - }; + let allocation = Allocation { claimee, amount, timestamp, vintage, id }; self.Offsetter_allocations_claimed.entry(allocation).write(true); // [Emit event] @@ -247,12 +240,11 @@ pub mod OffsetComponent { claimee: ContractAddress, timestamp: u128, amount: u128, + vintage: u256, id: u128 ) -> bool { // Check if claimee has already claimed this allocation, by checking in the mapping - let allocation = Allocation { - claimee: claimee, amount: amount.into(), timestamp: timestamp.into(), id: id.into() - }; + let allocation = Allocation { claimee, amount, timestamp, vintage, id }; self.Offsetter_allocations_claimed.entry(allocation).read() } @@ -267,7 +259,7 @@ pub mod OffsetComponent { } #[generate_trait] - impl InternalImpl< + pub impl InternalImpl< TContractState, +HasComponent, +Drop, diff --git a/src/components/resale/interface.cairo b/src/components/resale/interface.cairo index b71661e..c869f99 100644 --- a/src/components/resale/interface.cairo +++ b/src/components/resale/interface.cairo @@ -1,8 +1,7 @@ use starknet::ContractAddress; -use carbon_v3::models::carbon_vintage::CarbonVintage; #[starknet::interface] -trait IResaleHandler { +pub trait IResaleHandler { /// Deposit carbon credits from one vintage for resale. fn deposit_vintage(ref self: TContractState, token_id: u256, cc_amount: u256); @@ -12,7 +11,12 @@ trait IResaleHandler { // Claim a reward assigned to caller fn claim( - ref self: TContractState, amount: u128, timestamp: u128, id: u128, proof: Array:: + ref self: TContractState, + amount: u128, + timestamp: u128, + vintage: u256, + id: u128, + proof: Array:: ); /// Get the pending amount of resale of a vintage for the caller address. @@ -29,7 +33,12 @@ trait IResaleHandler { /// Check if a reward has been claimed fn check_claimed( - self: @TContractState, claimee: ContractAddress, timestamp: u128, amount: u128, id: u128 + self: @TContractState, + claimee: ContractAddress, + timestamp: u128, + amount: u128, + vintage: u256, + id: u128 ) -> bool; /// Resale strategy for carbon credits diff --git a/src/components/resale/resale_handler.cairo b/src/components/resale/resale_handler.cairo index 4e77b13..3a62b20 100644 --- a/src/components/resale/resale_handler.cairo +++ b/src/components/resale/resale_handler.cairo @@ -1,5 +1,5 @@ #[starknet::component] -mod ResaleComponent { +pub mod ResaleComponent { // Core imports use core::hash::LegacyHash; @@ -13,14 +13,13 @@ mod ResaleComponent { // Internal imports use carbon_v3::components::resale::interface::IResaleHandler; - use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; + use carbon_v3::models::{CarbonVintage, CarbonVintageType, Allocation}; use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; - use carbon_v3::components::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; use carbon_v3::contracts::project::{ IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; - use carbon_v3::contracts::project::Project::OWNER_ROLE; + use carbon_v3::constants::OWNER_ROLE; use alexandria_merkle_tree::merkle_tree::{ Hasher, MerkleTree, MerkleTreeImpl, pedersen::PedersenHasherImpl, MerkleTreeTrait, @@ -28,16 +27,8 @@ mod ResaleComponent { use openzeppelin::access::accesscontrol::interface::IAccessControl; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; - #[derive(Copy, Drop, Debug, Hash, starknet::Store, Serde, PartialEq)] - struct Allocation { - claimee: ContractAddress, - amount: u128, - timestamp: u128, - id: u128 - } - #[storage] - struct Storage { + pub struct Storage { Resale_carbonable_project_address: ContractAddress, Resale_carbon_pending_resale: Map<(u256, ContractAddress), u256>, Resale_carbon_sold: Map<(u256, ContractAddress), u256>, @@ -50,7 +41,7 @@ mod ResaleComponent { #[event] #[derive(Drop, starknet::Event)] - enum Event { + pub enum Event { RequestedResale: RequestedResale, Resale: Resale, PendingResaleRemoved: PendingResaleRemoved, @@ -101,17 +92,18 @@ mod ResaleComponent { pub id: u128 } - mod Errors { - const NOT_ENOUGH_CARBON: felt252 = 'Resale: Not enough carbon'; - const NOT_ENOUGH_TOKENS: felt252 = 'Resale: Not enough tokens'; - const NOT_ENOUGH_PENDING: felt252 = 'Resale: Not enough pending'; - const EMPTY_INPUT: felt252 = 'Resale: Inputs cannot be empty'; - const ARRAY_MISMATCH: felt252 = 'Resale: Array length mismatch'; - const INVALID_PROOF: felt252 = 'Resale: Invalid proof'; - const ALREADY_CLAIMED: felt252 = 'Resale: Already claimed'; - const MISSING_ROLE: felt252 = 'Resale: Missing role'; - const ZERO_ADDRESS: felt252 = 'Resale: Address is invalid'; - const INVALID_DEPOSIT: felt252 = 'Resale: Invalid deposit'; + pub mod Errors { + pub const INVALID_VINTAGE: felt252 = 'Resale: Invalid vintage'; + pub const NOT_ENOUGH_CARBON: felt252 = 'Resale: Not enough carbon'; + pub const NOT_ENOUGH_TOKENS: felt252 = 'Resale: Not enough tokens'; + pub const NOT_ENOUGH_PENDING: felt252 = 'Resale: Not enough pending'; + pub const EMPTY_INPUT: felt252 = 'Resale: Inputs cannot be empty'; + pub const ARRAY_MISMATCH: felt252 = 'Resale: Array length mismatch'; + pub const INVALID_PROOF: felt252 = 'Resale: Invalid proof'; + pub const ALREADY_CLAIMED: felt252 = 'Resale: Already claimed'; + pub const MISSING_ROLE: felt252 = 'Resale: Missing role'; + pub const ZERO_ADDRESS: felt252 = 'Resale: Address is invalid'; + pub const INVALID_DEPOSIT: felt252 = 'Resale: Invalid deposit'; } #[embeddable_as(ResaleHandlerImpl)] @@ -129,7 +121,8 @@ mod ResaleComponent { let vintages = IVintageDispatcher { contract_address: project_address }; let stored_vintage: CarbonVintage = vintages.get_carbon_vintage(token_id); - assert(stored_vintage.status != CarbonVintageType::Unset, 'Vintage status is not set'); + let status: CarbonVintageType = stored_vintage.status; + assert(status != CarbonVintageType::Unset, Errors::INVALID_VINTAGE); let project = IProjectDispatcher { contract_address: project_address }; let caller_balance = project.balance_of(caller_address, token_id); @@ -164,6 +157,7 @@ mod ResaleComponent { ref self: ComponentState, amount: u128, timestamp: u128, + vintage: u256, id: u128, proof: Array:: ) { @@ -171,7 +165,7 @@ mod ResaleComponent { let claimee = get_caller_address(); // [Verify not already claimed] - let claimed = self.check_claimed(claimee, timestamp, amount, id); + let claimed = self.check_claimed(claimee, timestamp, amount, vintage, id); assert(!claimed, Errors::ALREADY_CLAIMED); // [Verify the proof] @@ -191,7 +185,7 @@ mod ResaleComponent { // [Mark as claimed] let allocation = Allocation { - claimee: claimee, amount: amount, timestamp: timestamp, id: id + claimee: claimee, amount: amount, timestamp: timestamp, vintage: 'todo', id: id }; self.Resale_allocations_claimed.entry(allocation).write(true); @@ -223,11 +217,16 @@ mod ResaleComponent { claimee: ContractAddress, timestamp: u128, amount: u128, + vintage: u256, id: u128 ) -> bool { // Check if claimee has already claimed this allocation, by checking in the mapping let allocation = Allocation { - claimee: claimee, amount: amount.into(), timestamp: timestamp.into(), id: id.into() + claimee: claimee, + amount: amount.into(), + timestamp: timestamp.into(), + vintage: 'toto', + id: id.into() }; self.Resale_allocations_claimed.entry(allocation).read() } @@ -303,7 +302,7 @@ mod ResaleComponent { } #[generate_trait] - impl InternalImpl< + pub impl InternalImpl< TContractState, +HasComponent, +Drop, diff --git a/src/components/vintage/interface.cairo b/src/components/vintage/interface.cairo index 29129e4..d6b3f9d 100644 --- a/src/components/vintage/interface.cairo +++ b/src/components/vintage/interface.cairo @@ -1,7 +1,7 @@ -use carbon_v3::models::carbon_vintage::CarbonVintage; +use carbon_v3::models::CarbonVintage; #[starknet::interface] -trait IVintage { +pub trait IVintage { /// Returns the project total carbon credits. fn get_project_carbon(self: @TContractState) -> u256; diff --git a/src/components/vintage/vintage.cairo b/src/components/vintage/vintage.cairo index 0688b3e..40b0591 100644 --- a/src/components/vintage/vintage.cairo +++ b/src/components/vintage/vintage.cairo @@ -1,5 +1,5 @@ #[starknet::component] -mod VintageComponent { +pub mod VintageComponent { // Starknet imports use starknet::get_caller_address; use starknet::storage::{ @@ -9,17 +9,17 @@ mod VintageComponent { // Internal imports use carbon_v3::components::vintage::interface::IVintage; - use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; + use carbon_v3::models::{CarbonVintage, CarbonVintageType}; // Constants - use carbon_v3::models::constants::CC_DECIMALS; - use carbon_v3::contracts::project::Project::OWNER_ROLE; + use carbon_v3::constants::{CC_DECIMALS, OWNER_ROLE}; + // Roles use openzeppelin::access::accesscontrol::interface::IAccessControl; #[storage] - struct Storage { + pub struct Storage { Vintage_vintages: Map, Vintage_vintages_len: usize, Vintage_project_carbon: u256, @@ -27,7 +27,7 @@ mod VintageComponent { #[event] #[derive(Drop, PartialEq, starknet::Event)] - enum Event { + pub enum Event { ProjectCarbonUpdated: ProjectCarbonUpdated, VintageUpdate: VintageUpdate, VintageRebased: VintageRebased, @@ -74,9 +74,9 @@ mod VintageComponent { new_vintage: CarbonVintage, } - mod Errors { - const INVALID_ARRAY_LENGTH: felt252 = 'Vintage: invalid array length'; - const INVALID_STARTING_YEAR: felt252 = 'Vintage: invalid starting year'; + pub mod Errors { + pub const INVALID_ARRAY_LENGTH: felt252 = 'Vintage: invalid array length'; + pub const INVALID_STARTING_YEAR: felt252 = 'Vintage: invalid starting year'; } #[embeddable_as(VintageImpl)] @@ -106,8 +106,8 @@ mod VintageComponent { if index >= num_vintages { break (); } - let token_id = (index + 1).into(); - let vintage = self.Vintage_vintages.read(token_id); + let token_id: u256 = (index + 1).into(); + let vintage = self.Vintage_vintages.entry(token_id).read(); vintages.append(vintage); index += 1; }; @@ -237,7 +237,7 @@ mod VintageComponent { } #[generate_trait] - impl InternalImpl< + pub impl InternalImpl< TContractState, +HasComponent, +Drop, diff --git a/src/constants.cairo b/src/constants.cairo new file mode 100644 index 0000000..79870e5 --- /dev/null +++ b/src/constants.cairo @@ -0,0 +1,14 @@ +// Carbon Credits amount, equals to tons of CO2 equivalent, is here expressed in grams of CO2 +// equivalent, with 2 decimals after the comma. +// Example: If Bob wants to buy 1.5 carbon credits, the input should be 1.5*CC_DECIMALS_MULTIPLIER = +// 150000000000000. + +pub const CC_DECIMALS_MULTIPLIER: u256 = 1_000_000_000_000_000_000; +pub const MULTIPLIER_TONS_TO_MGRAMS: u256 = 1_000_000_000; +pub const CC_DECIMALS: u8 = 8; + +pub const IERC165_BACKWARD_COMPATIBLE_ID: felt252 = 0x80ac58cd; +pub const OLD_IERC1155_ID: felt252 = 0xd9b67a26; +pub const MINTER_ROLE: felt252 = selector!("Minter"); +pub const OFFSETTER_ROLE: felt252 = selector!("Offsetter"); +pub const OWNER_ROLE: felt252 = selector!("Owner"); diff --git a/src/contracts/minter.cairo b/src/contracts/minter.cairo index 3f3b7a6..055c2c3 100644 --- a/src/contracts/minter.cairo +++ b/src/contracts/minter.cairo @@ -1,7 +1,5 @@ -use starknet::ContractAddress; - #[starknet::contract] -mod Minter { +pub mod Minter { use starknet::ContractAddress; // Ownable @@ -10,8 +8,6 @@ mod Minter { use openzeppelin::upgrades::upgradeable::UpgradeableComponent; // Mint use carbon_v3::components::minter::mint::MintComponent; - // RBAC interface - use openzeppelin::access::accesscontrol::interface::IAccessControl; component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/contracts/offsetter.cairo b/src/contracts/offsetter.cairo index 3670226..ab54dd2 100644 --- a/src/contracts/offsetter.cairo +++ b/src/contracts/offsetter.cairo @@ -1,5 +1,3 @@ -use starknet::ContractAddress; - #[starknet::contract] mod Offsetter { use starknet::ContractAddress; diff --git a/src/contracts/project.cairo b/src/contracts/project.cairo index 0807081..3000b5f 100644 --- a/src/contracts/project.cairo +++ b/src/contracts/project.cairo @@ -1,7 +1,7 @@ use starknet::{ContractAddress, ClassHash}; #[starknet::interface] -trait IExternal { +pub trait IExternal { fn mint(ref self: TContractState, to: ContractAddress, token_id: u256, value: u256); fn burn(ref self: TContractState, from: ContractAddress, token_id: u256, value: u256); fn batch_mint( @@ -76,26 +76,19 @@ trait IExternal { #[starknet::contract] -mod Project { - use carbon_v3::components::vintage::interface::IVintageDispatcher; +pub mod Project { + use core::num::traits::Zero; use starknet::{get_caller_address, ContractAddress, ClassHash}; - // Ownable + use carbon_v3::components::erc1155::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; + use carbon_v3::components::vintage::vintage::VintageComponent; + use carbon_v3::components::metadata::MetadataComponent; + use openzeppelin::access::ownable::OwnableComponent; - // Upgradable use openzeppelin::upgrades::upgradeable::UpgradeableComponent; use openzeppelin::upgrades::interface::IUpgradeable; - //SRC5 use openzeppelin::introspection::src5::SRC5Component; - // ERC1155 - use carbon_v3::components::erc1155::{ERC1155Component, erc1155::ERC1155HooksEmptyImpl}; - // Vintage - use carbon_v3::components::vintage::VintageComponent; - // Metadata - use carbon_v3::components::metadata::MetadataComponent; - // Access Control - RBAC use openzeppelin::access::accesscontrol::AccessControlComponent; - // ERC4906 use erc4906::erc4906_component::ERC4906Component; component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); @@ -131,13 +124,9 @@ mod Project { impl ERC4906InternalImpl = ERC4906Component::InternalImpl; // Constants - use carbon_v3::models::constants::CC_DECIMALS_MULTIPLIER; - - const IERC165_BACKWARD_COMPATIBLE_ID: felt252 = 0x80ac58cd; - const OLD_IERC1155_ID: felt252 = 0xd9b67a26; - const MINTER_ROLE: felt252 = selector!("Minter"); - const OFFSETTER_ROLE: felt252 = selector!("Offsetter"); - const OWNER_ROLE: felt252 = selector!("Owner"); + use carbon_v3::constants::{ + OWNER_ROLE, MINTER_ROLE, OFFSETTER_ROLE, IERC165_BACKWARD_COMPATIBLE_ID, OLD_IERC1155_ID + }; #[storage] struct Storage { @@ -191,9 +180,9 @@ mod Project { } - mod Errors { - const UNEQUAL_ARRAYS_URI: felt252 = 'URI Array len do not match'; - const INVALID_ARRAY_LENGTH: felt252 = 'ERC1155: no equal array length'; + pub mod Errors { + pub const UNEQUAL_ARRAYS_URI: felt252 = 'URI Array len do not match'; + pub const INVALID_ARRAY_LENGTH: felt252 = 'ERC1155: no equal array length'; } // Constructor @@ -466,7 +455,7 @@ mod Project { ERC1155Component::Event::TransferSingle( ERC1155Component::TransferSingle { operator: get_caller_address(), - from: Zeroable::zero(), + from: Zero::zero(), to, id: token_id, value: cc_value, @@ -495,7 +484,7 @@ mod Project { .emit( ERC1155Component::Event::TransferSingle( ERC1155Component::TransferSingle { - operator, from: Zeroable::zero(), to, id: token_id, value: cc_value, + operator, from: Zero::zero(), to, id: token_id, value: cc_value, } ) ); @@ -509,7 +498,7 @@ mod Project { // ERC1155Component::Event::TransferBatch( // ERC1155Component::TransferBatch { // operator: get_caller_address(), - // from: Zeroable::zero(), + // from: Zero::zero(), // to, // ids: token_ids, // values: values_to_emit, @@ -526,11 +515,7 @@ mod Project { .emit( ERC1155Component::Event::TransferSingle( ERC1155Component::TransferSingle { - operator: caller, - from, - to: Zeroable::zero(), - id: token_id, - value: cc_value, + operator: caller, from, to: Zero::zero(), id: token_id, value: cc_value, } ) ); @@ -561,7 +546,7 @@ mod Project { ERC1155Component::TransferSingle { operator: caller, from, - to: Zeroable::zero(), + to: Zero::zero(), id: token_id, value: cc_value, } @@ -577,7 +562,7 @@ mod Project { // ERC1155Component::TransferBatch { // operator: get_caller_address(), // from, - // to: Zeroable::zero(), + // to: Zero::zero(), // ids: token_ids, // values: values_to_emit, // } diff --git a/src/contracts/resale.cairo b/src/contracts/resale.cairo index c15196e..245b756 100644 --- a/src/contracts/resale.cairo +++ b/src/contracts/resale.cairo @@ -1,11 +1,9 @@ -use starknet::ContractAddress; - #[starknet::contract] mod Resale { use starknet::ContractAddress; // Constants - const OWNER_ROLE: felt252 = selector!("Owner"); + use carbon_v3::constants::OWNER_ROLE; // Ownable use openzeppelin::access::ownable::OwnableComponent; diff --git a/src/lib.cairo b/src/lib.cairo index 8d5a899..cd125b2 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,29 +1,41 @@ -mod components { - mod erc1155; - mod metadata; - mod minter; - mod offsetter; - mod resale { - mod interface; - mod resale_handler; +pub mod components { + pub mod erc1155 { + pub mod interface; + pub mod erc1155; + pub mod erc1155_receiver; + } + pub mod metadata; + pub mod minter { + pub mod booking; + pub mod interface; + pub mod mint; + } + pub mod offsetter { + pub mod interface; + pub mod offset_handler; + } + pub mod resale { + pub mod interface; + pub mod resale_handler; + } + pub mod vintage { + pub mod interface; + pub mod vintage; } - mod vintage; } -mod models { - mod carbon_vintage; - mod constants; -} +pub mod models; +pub mod constants; -mod contracts { - mod minter; - mod offsetter; - mod project; - mod resale; +pub mod contracts { + pub mod minter; + pub mod offsetter; + pub mod project; + pub mod resale; } -mod mock { - mod usdcarb; - mod metadata; +pub mod mock { + pub mod usdcarb; + pub mod metadata; } diff --git a/src/mock/metadata.cairo b/src/mock/metadata.cairo index 1473cab..1759fa2 100644 --- a/src/mock/metadata.cairo +++ b/src/mock/metadata.cairo @@ -1,6 +1,6 @@ #[starknet::contract] -mod TestContract { - use carbon_v3::components::metadata::{MetadataComponent, IMetadataHandler}; +pub mod TestContract { + use carbon_v3::components::metadata::MetadataComponent; component!(path: MetadataComponent, storage: metadata_uri, event: MetadataEvent); @@ -21,7 +21,7 @@ mod TestContract { } #[starknet::contract] -mod TestMetadata { +pub mod TestMetadata { use carbon_v3::components::metadata::IMetadataDescriptor; #[storage] diff --git a/src/mock/usdcarb.cairo b/src/mock/usdcarb.cairo index bab9865..21d0c80 100644 --- a/src/mock/usdcarb.cairo +++ b/src/mock/usdcarb.cairo @@ -2,16 +2,18 @@ use starknet::ContractAddress; #[starknet::interface] -trait IExternal { +pub trait IExternal { fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256); } #[starknet::contract] -mod USDCarb { +pub mod USDCarb { + use starknet::storage::StoragePointerReadAccess; + use starknet::ContractAddress; + use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl}; use openzeppelin::token::erc20::interface::IERC20Metadata; use openzeppelin::access::ownable::OwnableComponent; - use starknet::ContractAddress; component!(path: ERC20Component, storage: erc20, event: ERC20Event); component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); diff --git a/src/models/carbon_vintage.cairo b/src/models.cairo similarity index 92% rename from src/models/carbon_vintage.cairo rename to src/models.cairo index 314b1cd..730e3ec 100644 --- a/src/models/carbon_vintage.cairo +++ b/src/models.cairo @@ -1,18 +1,28 @@ use core::fmt::{Display, Formatter, Error}; +use starknet::ContractAddress; + + +#[derive(Copy, Drop, Debug, Hash, starknet::Store, Serde, PartialEq)] +pub struct Allocation { + pub claimee: ContractAddress, + pub amount: u128, + pub timestamp: u128, + pub vintage: u256, + pub id: u128 +} -/// Struct for orders. #[derive(Copy, Drop, Debug, starknet::Store, Serde, PartialEq, Default)] -struct CarbonVintage { +pub struct CarbonVintage { /// The year of the vintage - year: u32, + pub year: u32, /// The total supply of Carbon Credit for this vintage. - supply: u256, + pub supply: u256, /// The total amount of Carbon Credit that was failed during audits. - failed: u256, + pub failed: u256, /// The total amount of Carbon Credit that was created during audits. - created: u256, + pub created: u256, /// The status of the Carbon Credit of this Vintage. - status: CarbonVintageType, + pub status: CarbonVintageType, } impl CarbonVintageDisplay of Display { @@ -31,7 +41,7 @@ impl CarbonVintageDisplay of Display { } #[derive(Copy, Drop, Debug, starknet::Store, Serde, PartialEq, Default)] -enum CarbonVintageType { +pub enum CarbonVintageType { #[default] /// Unset: the Carbon Credit is not yet created nor projected. Unset, @@ -87,7 +97,6 @@ impl CarbonVintageTypeDisplay of Display { #[cfg(test)] mod Test { - use starknet::testing::set_caller_address; use super::{CarbonVintage, CarbonVintageType}; // CarbonVintage tests diff --git a/src/models/constants.cairo b/src/models/constants.cairo deleted file mode 100644 index 9890771..0000000 --- a/src/models/constants.cairo +++ /dev/null @@ -1,8 +0,0 @@ -// Carbon Credits amount, equals to tons of CO2 equivalent, is here expressed in grams of CO2 -// equivalent, with 2 decimals after the comma. -// Example: If Bob wants to buy 1.5 carbon credits, the input should be 1.5*CC_DECIMALS_MULTIPLIER = -// 150000000000000. - -const CC_DECIMALS_MULTIPLIER: u256 = 1_000_000_000_000_000_000; -const MULTIPLIER_TONS_TO_MGRAMS: u256 = 1_000_000_000; -const CC_DECIMALS: u8 = 8; diff --git a/tests/lib.cairo b/tests/lib.cairo index 4580870..62c1ffb 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -1,8 +1,8 @@ -mod tests_lib; -mod test_merkle_tree; -mod test_mint; -mod test_offsetter; -mod test_project; -mod test_resale; -mod test_vintage; +pub mod tests_lib; +pub mod test_merkle_tree; +pub mod test_mint; +pub mod test_offsetter; +pub mod test_project; +pub mod test_resale; +pub mod test_vintage; diff --git a/tests/test_merkle_tree.cairo b/tests/test_merkle_tree.cairo index 30f00d4..dc015db 100644 --- a/tests/test_merkle_tree.cairo +++ b/tests/test_merkle_tree.cairo @@ -1,23 +1,18 @@ use starknet::{ContractAddress, contract_address_const}; -use snforge_std as snf; -use snforge_std::{ - ContractClassTrait, spy_events, EventSpy, start_cheat_caller_address, stop_cheat_caller_address, - EventSpyAssertionsTrait -}; +use snforge_std::{start_cheat_caller_address}; // Contracts use carbon_v3::components::offsetter::interface::{ IOffsetHandlerDispatcher, IOffsetHandlerDispatcherTrait }; -use carbon_v3::components::offsetter::OffsetComponent; /// Utils for testing purposes use super::tests_lib::{default_setup_and_deploy, deploy_offsetter}; /// Utils to import mock data use super::tests_lib::{ - MERKLE_ROOT_FIRST_WAVE, MERKLE_ROOT_SECOND_WAVE, get_bob_first_wave_allocation, - get_bob_second_wave_allocation, get_alice_second_wave_allocation, get_john_multiple_allocations + MERKLE_ROOT_FIRST_WAVE, get_bob_first_wave_allocation, get_bob_second_wave_allocation, + get_alice_second_wave_allocation, get_john_multiple_allocations }; #[test] @@ -66,7 +61,7 @@ fn test_bob_claims_single_allocation() { start_cheat_caller_address(offsetter_address, bob_address); assert_eq!(contract.get_merkle_root(), root); - assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, 1, id, proof)); } #[test] @@ -81,9 +76,9 @@ fn test_claim_with_invalid_address() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); let invalid_address = contract_address_const::<'DUMMY'>(); - assert!(!contract.check_claimed(invalid_address, timestamp, amount, id)); + assert!(!contract.check_claimed(invalid_address, timestamp, amount, 1, id)); - assert!(!contract.confirm_for_merkle_tree(invalid_address, amount, timestamp, id, proof)); + assert!(!contract.confirm_for_merkle_tree(invalid_address, amount, timestamp, 1, id, proof)); } #[test] @@ -98,9 +93,11 @@ fn test_claim_with_invalid_amount() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); let invalid_amount = 0; - assert!(!contract.check_claimed(bob_address, timestamp, invalid_amount, id)); + assert!(!contract.check_claimed(bob_address, timestamp, invalid_amount, 1, id)); - assert!(!contract.confirm_for_merkle_tree(bob_address, invalid_amount, timestamp, id, proof)); + assert!( + !contract.confirm_for_merkle_tree(bob_address, invalid_amount, timestamp, 1, id, proof) + ); } #[test] @@ -115,9 +112,11 @@ fn test_claim_with_invalid_timestamp() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); let invalid_timestamp = 0; - assert!(!contract.check_claimed(bob_address, invalid_timestamp, amount, id)); + assert!(!contract.check_claimed(bob_address, invalid_timestamp, amount, 1, id)); - assert!(!contract.confirm_for_merkle_tree(bob_address, amount, invalid_timestamp, id, proof)); + assert!( + !contract.confirm_for_merkle_tree(bob_address, amount, invalid_timestamp, 1, id, proof) + ); } #[test] @@ -132,9 +131,11 @@ fn test_claim_with_invalid_proof() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); let invalid_proof: Array = array![0x123, 0x1]; - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); + assert!(!contract.check_claimed(bob_address, timestamp, amount, 1, id)); - assert!(!contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, invalid_proof)); + assert!( + !contract.confirm_for_merkle_tree(bob_address, amount, timestamp, 1, id, invalid_proof) + ); } #[test] @@ -149,13 +150,13 @@ fn test_claim_after_root_update() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); + assert!(!contract.check_claimed(bob_address, timestamp, amount, 1, id)); let (new_root, _, _, _, _, new_proof) = get_bob_second_wave_allocation(); contract.set_merkle_root(new_root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); + assert!(!contract.check_claimed(bob_address, timestamp, amount, 1, id)); - assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, new_proof)); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, 1, id, new_proof)); } #[test] @@ -170,17 +171,17 @@ fn test_alice_claims_in_second_wave() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); - assert!(!contract.check_claimed(bob_address, timestamp, amount, id)); + assert!(!contract.check_claimed(bob_address, timestamp, amount, 1, id)); - assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, id, proof)); + assert!(contract.confirm_for_merkle_tree(bob_address, amount, timestamp, 1, id, proof)); let (new_root, alice_address, amount, timestamp, id, proof) = get_alice_second_wave_allocation(); start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(new_root); - assert!(!contract.check_claimed(alice_address, timestamp, amount, id)); + assert!(!contract.check_claimed(alice_address, timestamp, amount, 1, id)); - assert!(contract.confirm_for_merkle_tree(alice_address, amount, timestamp, id, proof)); + assert!(contract.confirm_for_merkle_tree(alice_address, amount, timestamp, 1, id, proof)); } #[test] @@ -217,15 +218,15 @@ fn test_john_claims_multiple_allocations() { start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(root); - assert!(!contract.check_claimed(john_address, timestamp1, amount1, id_1)); - assert!(!contract.check_claimed(john_address, timestamp2, amount2, id_2)); - assert!(!contract.check_claimed(john_address, timestamp3, amount3, id_3)); + assert!(!contract.check_claimed(john_address, timestamp1, amount1, 1, id_1)); + assert!(!contract.check_claimed(john_address, timestamp2, amount2, 1, id_2)); + assert!(!contract.check_claimed(john_address, timestamp3, amount3, 1, id_3)); - assert!(contract.confirm_for_merkle_tree(john_address, amount1, timestamp1, id_1, proof1)); - assert!(contract.confirm_for_merkle_tree(john_address, amount2, timestamp2, id_2, proof2)); + assert!(contract.confirm_for_merkle_tree(john_address, amount1, timestamp1, 1, id_1, proof1)); + assert!(contract.confirm_for_merkle_tree(john_address, amount2, timestamp2, 1, id_2, proof2)); start_cheat_caller_address(offsetter_address, owner_address); contract.set_merkle_root(new_root); - assert!(contract.confirm_for_merkle_tree(john_address, amount4, timestamp4, id_4, proof4)); + assert!(contract.confirm_for_merkle_tree(john_address, amount4, timestamp4, 1, id_4, proof4)); } diff --git a/tests/test_mint.cairo b/tests/test_mint.cairo index d345f99..881f073 100644 --- a/tests/test_mint.cairo +++ b/tests/test_mint.cairo @@ -1,3 +1,5 @@ +use core::num::traits::Zero; + // Starknet deps use starknet::{ContractAddress, contract_address_const}; @@ -5,44 +7,38 @@ use starknet::{ContractAddress, contract_address_const}; // External deps use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use openzeppelin::token::erc20::interface::ERC20ABIDispatcherTrait; -use openzeppelin::token::erc1155::ERC1155Component; use snforge_std as snf; use snforge_std::{ - ContractClassTrait, DeclareResultTrait, test_address, spy_events, EventSpy, CheatSpan, - start_cheat_caller_address, stop_cheat_caller_address, EventSpyAssertionsTrait + ContractClassTrait, DeclareResultTrait, spy_events, start_cheat_caller_address, + stop_cheat_caller_address, EventSpyAssertionsTrait }; // Components use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; -use carbon_v3::components::vintage::VintageComponent; use carbon_v3::components::minter::interface::{IMintDispatcher, IMintDispatcherTrait}; -use carbon_v3::components::minter::MintComponent; +use carbon_v3::components::minter::mint::MintComponent; // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; -use carbon_v3::contracts::minter::Minter; -use carbon_v3::mock::usdcarb::USDCarb; // Utils for testing purposes use super::tests_lib::{ get_mock_absorptions, equals_with_error, deploy_project, setup_project, - default_setup_and_deploy, deploy_offsetter, deploy_erc20, deploy_minter, buy_utils, - helper_get_token_ids, helper_sum_balance, DEFAULT_REMAINING_MINTABLE_CC, - helper_check_vintage_balances, get_mock_absorptions_times_2, helper_expected_transfer_event, - helper_expected_transfer_single_events, helper_get_cc_amounts + default_setup_and_deploy, deploy_erc20, deploy_minter, buy_utils, helper_get_token_ids, + helper_sum_balance, helper_check_vintage_balances, get_mock_absorptions_times_2, + helper_expected_transfer_single_events, DEFAULT_REMAINING_MINTABLE_CC }; // Constants -use carbon_v3::models::constants::{MULTIPLIER_TONS_TO_MGRAMS}; +use carbon_v3::constants::MULTIPLIER_TONS_TO_MGRAMS; + const PROJECT_CARBON: u256 = 42; // Signers @@ -267,7 +263,7 @@ fn test_public_buy() { // }; let expected_events = helper_expected_transfer_single_events( - project_address, minter_address, Zeroable::zero(), user_address, token_ids, cc_to_buy + project_address, minter_address, Zero::zero(), user_address, token_ids, cc_to_buy ); spy.assert_emitted(@expected_events); @@ -313,7 +309,7 @@ fn test_minimal_buy() { let token_ids = helper_get_token_ids(project_address); let expected_events = helper_expected_transfer_single_events( - project_address, minter_address, Zeroable::zero(), user_address, token_ids, cc_to_buy + project_address, minter_address, Zero::zero(), user_address, token_ids, cc_to_buy ); spy.assert_emitted(@expected_events); } @@ -356,7 +352,7 @@ fn test_minimal_buy_error() { let token_ids = helper_get_token_ids(project_address); let expected_events = helper_expected_transfer_single_events( - project_address, minter_address, Zeroable::zero(), user_address, token_ids, cc_to_buy + project_address, minter_address, Zero::zero(), user_address, token_ids, cc_to_buy ); spy.assert_emitted(@expected_events); } diff --git a/tests/test_offsetter.cairo b/tests/test_offsetter.cairo index 3ac9db4..6b4aaba 100644 --- a/tests/test_offsetter.cairo +++ b/tests/test_offsetter.cairo @@ -3,35 +3,22 @@ use starknet::{ContractAddress, contract_address_const}; // External deps - -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; - -use snforge_std as snf; -use snforge_std::{ - ContractClassTrait, test_address, spy_events, EventSpy, start_cheat_caller_address, - stop_cheat_caller_address, -}; -use snforge_std::cheatcodes::events::{EventsFilterTrait, EventSpyTrait, EventSpyAssertionsTrait}; +use snforge_std::{spy_events, start_cheat_caller_address, stop_cheat_caller_address,}; +use snforge_std::cheatcodes::events::EventSpyAssertionsTrait; // Components use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; -use carbon_v3::models::carbon_vintage::CarbonVintageType; -use carbon_v3::components::vintage::VintageComponent; -use carbon_v3::components::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use carbon_v3::models::CarbonVintageType; use carbon_v3::components::offsetter::interface::{ IOffsetHandlerDispatcher, IOffsetHandlerDispatcherTrait }; -use carbon_v3::components::offsetter::OffsetComponent; +use carbon_v3::components::offsetter::offset_handler::OffsetComponent; // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; -use carbon_v3::contracts::minter::Minter; -use carbon_v3::mock::usdcarb::USDCarb; - // Utils for testing purposes use super::tests_lib::{ @@ -59,8 +46,7 @@ struct Contracts { /// Utils to import mock data use super::tests_lib::{ - MERKLE_ROOT_FIRST_WAVE, MERKLE_ROOT_SECOND_WAVE, get_bob_first_wave_allocation, - get_bob_second_wave_allocation, get_alice_second_wave_allocation, get_john_multiple_allocations + get_bob_first_wave_allocation, get_alice_second_wave_allocation, get_john_multiple_allocations }; // @@ -584,9 +570,9 @@ fn test_confirm_offset() { let current_retirement = offsetter.get_retirement(token_id, bob_address); let new_retirement = current_retirement + amount.clone().into(); - assert!(!offsetter.check_claimed(bob_address, timestamp, amount, id)); - offsetter.confirm_offset(amount, timestamp, id, proof); - assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + assert!(!offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement) } @@ -658,10 +644,10 @@ fn test_bob_confirms_twice() { let final_balance = project.balance_of(bob_address, token_id); assert(final_balance == initial_balance - amount_to_offset, 'Balance is wrong'); - offsetter.confirm_offset(amount, timestamp, id, proof.clone()); - assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof.clone()); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); - offsetter.confirm_offset(amount, timestamp, id, proof); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof); } @@ -734,7 +720,7 @@ fn test_events_emission_on_claim_confirmation() { let new_retirement = current_retirement + amount.clone().into(); let mut spy = spy_events(); - offsetter.confirm_offset(amount, timestamp, id, proof); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof); let first_expected_event = OffsetComponent::Event::Retired( OffsetComponent::Retired { @@ -758,7 +744,7 @@ fn test_events_emission_on_claim_confirmation() { ] ); - assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); } @@ -830,7 +816,7 @@ fn test_claim_confirmation_with_invalid_amount() { let invalid_amount = 0; - offsetter.confirm_offset(invalid_amount, timestamp, id, proof); + offsetter.confirm_offset(invalid_amount, timestamp, token_id, id, proof); } #[test] @@ -903,9 +889,9 @@ fn test_alice_confirms_in_second_wave() { let current_retirement = offsetter.get_retirement(token_id, bob_address); let new_retirement = current_retirement + amount.clone().into(); - assert!(!offsetter.check_claimed(bob_address, timestamp, amount, id)); - offsetter.confirm_offset(amount, timestamp, id, proof); - assert!(offsetter.check_claimed(bob_address, timestamp, amount, id)); + assert!(!offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof); + assert!(offsetter.check_claimed(bob_address, timestamp, amount, token_id, id)); assert!(offsetter.get_retirement(token_id, bob_address) == new_retirement); @@ -967,9 +953,9 @@ fn test_alice_confirms_in_second_wave() { let current_retirement = offsetter.get_retirement(token_id, alice_address); let new_retirement = current_retirement + amount.clone().into(); - assert!(!offsetter.check_claimed(alice_address, timestamp, amount, id)); - offsetter.confirm_offset(amount, timestamp, id, proof); - assert!(offsetter.check_claimed(alice_address, timestamp, amount, id)); + assert!(!offsetter.check_claimed(alice_address, timestamp, amount, token_id, id)); + offsetter.confirm_offset(amount, timestamp, token_id, id, proof); + assert!(offsetter.check_claimed(alice_address, timestamp, amount, token_id, id)); assert!(offsetter.get_retirement(token_id, alice_address) == new_retirement); } @@ -1046,15 +1032,15 @@ fn test_john_confirms_multiple_allocations() { start_cheat_caller_address(project_address, offsetter_address); offsetter.deposit_vintage(token_id, amount1_to_offset); - assert!(!offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); - offsetter.confirm_offset(amount1, timestamp1, id_1, proof1); + assert!(!offsetter.check_claimed(john_address, timestamp1, amount1, token_id, id_1)); + offsetter.confirm_offset(amount1, timestamp1, token_id, id_1, proof1); offsetter.deposit_vintage(token_id, amount2_to_offset); - assert!(!offsetter.check_claimed(john_address, timestamp2, amount2, id_2)); - offsetter.confirm_offset(amount2, timestamp2, id_2, proof2); + assert!(!offsetter.check_claimed(john_address, timestamp2, amount2, token_id, id_2)); + offsetter.confirm_offset(amount2, timestamp2, token_id, id_2, proof2); - assert!(offsetter.check_claimed(john_address, timestamp1, amount1, id_1)); - assert!(offsetter.check_claimed(john_address, timestamp2, amount2, id_2)); + assert!(offsetter.check_claimed(john_address, timestamp1, amount1, token_id, id_1)); + assert!(offsetter.check_claimed(john_address, timestamp2, amount2, token_id, id_2)); start_cheat_caller_address(offsetter_address, owner_address); offsetter.set_merkle_root(new_root); @@ -1063,8 +1049,8 @@ fn test_john_confirms_multiple_allocations() { start_cheat_caller_address(project_address, offsetter_address); offsetter.deposit_vintage(token_id, amount4_to_offset); - assert!(!offsetter.check_claimed(john_address, timestamp4, amount4, id_4)); - offsetter.confirm_offset(amount4, timestamp4, id_4, proof4); + assert!(!offsetter.check_claimed(john_address, timestamp4, amount4, token_id, id_4)); + offsetter.confirm_offset(amount4, timestamp4, token_id, id_4, proof4); - assert!(offsetter.check_claimed(john_address, timestamp4, amount4, id_4)); + assert!(offsetter.check_claimed(john_address, timestamp4, amount4, token_id, id_4)); } diff --git a/tests/test_project.cairo b/tests/test_project.cairo index 1a37735..31b9b9f 100644 --- a/tests/test_project.cairo +++ b/tests/test_project.cairo @@ -1,5 +1,6 @@ // Starknet deps +use core::num::traits::Zero; use starknet::{ContractAddress, contract_address_const, get_caller_address}; // External deps @@ -7,41 +8,33 @@ use starknet::{ContractAddress, contract_address_const, get_caller_address}; use openzeppelin::token::erc1155::ERC1155Component; use snforge_std as snf; use snforge_std::{ - ContractClassTrait, DeclareResultTrait, EventSpy, start_cheat_caller_address, - stop_cheat_caller_address, spy_events, - cheatcodes::events::{EventSpyAssertionsTrait, EventSpyTrait, EventsFilterTrait} + DeclareResultTrait, EventSpy, start_cheat_caller_address, stop_cheat_caller_address, spy_events, + cheatcodes::events::{EventSpyAssertionsTrait} }; // Models -use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; -use carbon_v3::models::constants::{CC_DECIMALS_MULTIPLIER, MULTIPLIER_TONS_TO_MGRAMS}; +use carbon_v3::models::CarbonVintageType; +use carbon_v3::constants::MULTIPLIER_TONS_TO_MGRAMS; // Components -use carbon_v3::components::vintage::interface::{ - IVintage, IVintageDispatcher, IVintageDispatcherTrait -}; -use carbon_v3::components::minter::interface::{IMint, IMintDispatcher, IMintDispatcherTrait}; -use carbon_v3::components::metadata::{IMetadataHandlerDispatcher, IMetadataHandlerDispatcherTrait}; +use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; use erc4906::erc4906_component::ERC4906Component; // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; /// Utils for testing purposes /// use super::tests_lib::{ - equals_with_error, deploy_project, setup_project, default_setup_and_deploy, - perform_fuzzed_transfer, buy_utils, deploy_erc20, deploy_minter, deploy_offsetter, - helper_sum_balance, helper_check_vintage_balances, helper_get_token_ids, - helper_expected_transfer_event, helper_expected_transfer_single_events, helper_get_cc_amounts + equals_with_error, default_setup_and_deploy, perform_fuzzed_transfer, buy_utils, deploy_erc20, + deploy_minter, deploy_offsetter, helper_sum_balance, helper_check_vintage_balances, + helper_get_token_ids, helper_expected_transfer_event, helper_expected_transfer_single_events }; #[test] @@ -73,7 +66,7 @@ fn test_project_mint() { let expected_event_1155_transfer_single = helper_expected_transfer_event( project_address, minter_address, - Zeroable::zero(), + Zero::zero(), user_address, array![token_id].span(), cc_to_mint @@ -163,7 +156,7 @@ fn test_project_batch_mint_with_minter_role() { project.batch_mint(user_address, token_ids, values.span()); let expected_events = helper_expected_transfer_single_events( - project_address, minter_address, Zeroable::zero(), user_address, token_ids, cc_to_mint + project_address, minter_address, Zero::zero(), user_address, token_ids, cc_to_mint ); spy.assert_emitted(@expected_events); @@ -213,7 +206,7 @@ fn test_project_burn_with_offsetter_role() { project_address, offsetter_address, user_address, - Zeroable::zero(), + Zero::zero(), array![token_id].span(), balance ); @@ -295,7 +288,7 @@ fn test_project_batch_burn_with_offsetter_role() { project.batch_burn(user_address, token_ids, values.span()); let expected_events = helper_expected_transfer_single_events( - project_address, offsetter_address, user_address, Zeroable::zero(), token_ids, cc_to_burn + project_address, offsetter_address, user_address, Zero::zero(), token_ids, cc_to_burn ); spy.assert_emitted(@expected_events); } diff --git a/tests/test_resale.cairo b/tests/test_resale.cairo index 0447416..9c47cae 100644 --- a/tests/test_resale.cairo +++ b/tests/test_resale.cairo @@ -6,18 +6,12 @@ use starknet::{ContractAddress, contract_address_const}; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use snforge_std as snf; -use snforge_std::{ - ContractClassTrait, test_address, spy_events, EventSpy, start_cheat_caller_address, - stop_cheat_caller_address -}; -use snforge_std::cheatcodes::events::{EventsFilterTrait, EventSpyTrait, EventSpyAssertionsTrait}; +use snforge_std::{spy_events, start_cheat_caller_address, stop_cheat_caller_address}; +use snforge_std::cheatcodes::events::{EventSpyAssertionsTrait}; // Components use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; -use carbon_v3::models::carbon_vintage::CarbonVintageType; -use carbon_v3::components::vintage::VintageComponent; -use carbon_v3::components::erc1155::interface::{IERC1155Dispatcher, IERC1155DispatcherTrait}; +use carbon_v3::models::CarbonVintageType; use carbon_v3::components::resale::interface::{ IResaleHandlerDispatcher, IResaleHandlerDispatcherTrait }; @@ -25,11 +19,9 @@ use carbon_v3::components::resale::interface::{ // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; -use carbon_v3::contracts::minter::Minter; -use carbon_v3::mock::usdcarb::USDCarb; + // Utils for testing purposes diff --git a/tests/test_vintage.cairo b/tests/test_vintage.cairo index 10b2ae4..64b0286 100644 --- a/tests/test_vintage.cairo +++ b/tests/test_vintage.cairo @@ -4,32 +4,25 @@ use starknet::{ContractAddress, contract_address_const}; // External deps -use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -use snforge_std as snf; -use snforge_std::{ - ContractClassTrait, test_address, spy_events, EventSpy, start_cheat_caller_address, - stop_cheat_caller_address -}; +use snforge_std::{start_cheat_caller_address, stop_cheat_caller_address}; // Components use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; -use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; -use carbon_v3::components::vintage::VintageComponent; +use carbon_v3::models::{CarbonVintage, CarbonVintageType}; + // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; // Utils for testing purposes use super::tests_lib::{ - 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, STARTING_YEAR + get_mock_absorptions, deploy_project, default_setup_and_deploy, buy_utils, deploy_minter, + deploy_erc20, STARTING_YEAR }; // Constants diff --git a/tests/tests_lib.cairo b/tests/tests_lib.cairo index de49fe4..2dc856e 100644 --- a/tests/tests_lib.cairo +++ b/tests/tests_lib.cairo @@ -6,29 +6,24 @@ use starknet::{ContractAddress, contract_address_const}; use snforge_std as snf; use snforge_std::{ - ContractClassTrait, DeclareResultTrait, EventSpy, spy_events, EventSpyTrait, - EventSpyAssertionsTrait, start_cheat_caller_address, stop_cheat_caller_address + ContractClassTrait, DeclareResultTrait, start_cheat_caller_address, stop_cheat_caller_address }; // Models -use carbon_v3::models::carbon_vintage::{CarbonVintage, CarbonVintageType}; -use carbon_v3::models::constants::{CC_DECIMALS_MULTIPLIER, MULTIPLIER_TONS_TO_MGRAMS}; +use carbon_v3::constants::{CC_DECIMALS_MULTIPLIER, MULTIPLIER_TONS_TO_MGRAMS}; // Components -use carbon_v3::components::vintage::interface::{ - IVintage, IVintageDispatcher, IVintageDispatcherTrait -}; -use carbon_v3::components::minter::interface::{IMint, IMintDispatcher, IMintDispatcherTrait}; +use carbon_v3::components::vintage::interface::{IVintageDispatcher, IVintageDispatcherTrait}; +use carbon_v3::components::minter::interface::{IMintDispatcher, IMintDispatcherTrait}; use openzeppelin::token::erc1155::ERC1155Component; // Contracts use carbon_v3::contracts::project::{ - Project, IExternalDispatcher as IProjectDispatcher, - IExternalDispatcherTrait as IProjectDispatcherTrait + IExternalDispatcher as IProjectDispatcher, IExternalDispatcherTrait as IProjectDispatcherTrait }; use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; @@ -37,10 +32,10 @@ use openzeppelin::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTr /// Mock Data /// -const DEFAULT_REMAINING_MINTABLE_CC: u256 = 82500000000000; -const STARTING_YEAR: u32 = 2024; +pub const DEFAULT_REMAINING_MINTABLE_CC: u256 = 82500000000000; +pub const STARTING_YEAR: u32 = 2024; -fn get_mock_absorptions() -> Span { +pub fn get_mock_absorptions() -> Span { let absorptions: Span = array![ 0, 100000000000, @@ -81,7 +76,7 @@ fn get_mock_absorptions() -> Span { yearly_absorptions } -fn get_mock_absorptions_times_2() -> Span { +pub fn get_mock_absorptions_times_2() -> Span { let yearly_absorptions: Span = get_mock_absorptions(); let mut yearly_absorptions_times_2: Array = array![]; let mut index = 0; @@ -100,7 +95,7 @@ fn get_mock_absorptions_times_2() -> Span { /// Math functions /// -fn equals_with_error(a: u256, b: u256, error: u256) -> bool { +pub fn equals_with_error(a: u256, b: u256, error: u256) -> bool { let diff = if a > b { a - b } else { @@ -113,7 +108,7 @@ fn equals_with_error(a: u256, b: u256, error: u256) -> bool { /// Deploy and setup functions /// -fn deploy_project() -> ContractAddress { +pub fn deploy_project() -> ContractAddress { let contract = snf::declare("Project").expect('Declaration failed').contract_class(); let number_of_years: u64 = 20; let mut calldata: Array = array![ @@ -124,7 +119,7 @@ fn deploy_project() -> ContractAddress { contract_address } -fn setup_project(contract_address: ContractAddress, yearly_absorptions: Span) { +pub fn setup_project(contract_address: ContractAddress, yearly_absorptions: Span) { let vintages = IVintageDispatcher { contract_address }; // Fake the owner to call set_vintages and set_project_carbon which can only be run by owner let owner_address: ContractAddress = contract_address_const::<'OWNER'>(); @@ -133,7 +128,7 @@ fn setup_project(contract_address: ContractAddress, yearly_absorptions: Span ContractAddress { +pub fn default_setup_and_deploy() -> ContractAddress { let project_address = deploy_project(); let yearly_absorptions: Span = get_mock_absorptions(); setup_project(project_address, yearly_absorptions); @@ -141,7 +136,7 @@ fn default_setup_and_deploy() -> ContractAddress { } /// Deploys the offsetter contract. -fn deploy_offsetter(project_address: ContractAddress) -> ContractAddress { +pub fn deploy_offsetter(project_address: ContractAddress) -> ContractAddress { let contract = snf::declare("Offsetter").expect('Declaration failed').contract_class(); let owner: ContractAddress = contract_address_const::<'OWNER'>(); let mut calldata: Array = array![]; @@ -154,7 +149,7 @@ fn deploy_offsetter(project_address: ContractAddress) -> ContractAddress { } /// Deploys the resale contract. -fn deploy_resale( +pub fn deploy_resale( project_address: ContractAddress, token_address: ContractAddress ) -> ContractAddress { let contract = snf::declare("Resale").expect('Declaration failed').contract_class(); @@ -170,7 +165,7 @@ fn deploy_resale( } /// Deploys a minter contract. -fn deploy_minter( +pub fn deploy_minter( project_address: ContractAddress, payment_address: ContractAddress ) -> ContractAddress { let contract = snf::declare("Minter").expect('Declaration failed').contract_class(); @@ -195,7 +190,7 @@ fn deploy_minter( contract_address } -fn deploy_minter_specific_max_mintable( +pub fn deploy_minter_specific_max_mintable( project_address: ContractAddress, payment_address: ContractAddress, max_mintable_cc: u256 ) -> ContractAddress { let contract = snf::declare("Minter").expect('Declaration failed').contract_class(); @@ -221,7 +216,7 @@ fn deploy_minter_specific_max_mintable( } /// Deploy erc20 contract. -fn deploy_erc20() -> ContractAddress { +pub fn deploy_erc20() -> ContractAddress { let contract = snf::declare("USDCarb").expect('Declaration failed').contract_class(); let owner: ContractAddress = contract_address_const::<'OWNER'>(); let mut calldata: Array = array![]; @@ -232,7 +227,7 @@ fn deploy_erc20() -> ContractAddress { contract_address } -fn fuzzing_setup(cc_supply: u256) -> (ContractAddress, ContractAddress, ContractAddress) { +pub fn fuzzing_setup(cc_supply: u256) -> (ContractAddress, ContractAddress, ContractAddress) { let project_address = deploy_project(); let erc20_address = deploy_erc20(); let minter_address = deploy_minter_specific_max_mintable( @@ -259,7 +254,7 @@ fn fuzzing_setup(cc_supply: u256) -> (ContractAddress, ContractAddress, Contract /// That amount is minted across all vintages /// If Bob buys 100 carbon credits, and the vintage 2024 has 10% of the total supply, /// Bob will have 10 carbon credits in 2024 -fn buy_utils( +pub fn buy_utils( owner_address: ContractAddress, caller_address: ContractAddress, minter_address: ContractAddress, @@ -299,7 +294,7 @@ fn buy_utils( /// Tests functions to be called by the test runner /// -fn perform_fuzzed_transfer( +pub fn perform_fuzzed_transfer( raw_supply: u256, raw_cc_amount: u256, percentage_of_balance_to_send: u256, @@ -365,7 +360,7 @@ fn perform_fuzzed_transfer( assert(equals_with_error(balance_vintage_receiver, 0, 100), 'Error balance vintage receiver'); } -fn helper_get_token_ids(project_address: ContractAddress) -> Span { +pub fn helper_get_token_ids(project_address: ContractAddress) -> Span { let vintages = IVintageDispatcher { contract_address: project_address }; let num_vintages: usize = vintages.get_num_vintages(); let mut tokens: Array = Default::default(); @@ -381,7 +376,7 @@ fn helper_get_token_ids(project_address: ContractAddress) -> Span { tokens.span() } -fn helper_sum_balance(project_address: ContractAddress, user_address: ContractAddress) -> u256 { +pub fn helper_sum_balance(project_address: ContractAddress, user_address: ContractAddress) -> u256 { let project = IProjectDispatcher { contract_address: project_address }; let vintage = IVintageDispatcher { contract_address: project_address }; let num_vintages: usize = vintage.get_num_vintages(); @@ -400,7 +395,7 @@ fn helper_sum_balance(project_address: ContractAddress, user_address: ContractAd total_balance } -fn helper_check_vintage_balances( +pub fn helper_check_vintage_balances( project_address: ContractAddress, user_address: ContractAddress, total_cc_bought: u256 ) { let project = IProjectDispatcher { contract_address: project_address }; @@ -424,7 +419,7 @@ fn helper_check_vintage_balances( }; } -fn helper_check_vintage_balance( +pub fn helper_check_vintage_balance( project_address: ContractAddress, user_address: ContractAddress, token_id: u256, @@ -442,7 +437,7 @@ fn helper_check_vintage_balance( } -fn helper_get_cc_amounts( +pub fn helper_get_cc_amounts( project_address: ContractAddress, token_ids: Span, cc_to_buy: u256 ) -> Span { let project = IProjectDispatcher { contract_address: project_address }; @@ -461,7 +456,7 @@ fn helper_get_cc_amounts( } -fn helper_expected_transfer_event( +pub fn helper_expected_transfer_event( project_address: ContractAddress, operator: ContractAddress, from: ContractAddress, @@ -495,7 +490,7 @@ fn helper_expected_transfer_event( } -fn helper_expected_transfer_single_events( +pub fn helper_expected_transfer_single_events( project_address: ContractAddress, operator: ContractAddress, from: ContractAddress,