From 8c98c3861a42d4d0ed08a20002a05b46e1b7f831 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:34:12 +0000 Subject: [PATCH 1/9] assignments 1 --- yahia008/assignment_1/.gitignore | 1 + yahia008/assignment_1/Scarb.lock | 6 ++ yahia008/assignment_1/Scarb.toml | 14 +++++ yahia008/assignment_1/src/assignment1.cairo | 62 +++++++++++++++++++++ yahia008/assignment_1/src/lib.cairo | 1 + 5 files changed, 84 insertions(+) create mode 100644 yahia008/assignment_1/.gitignore create mode 100644 yahia008/assignment_1/Scarb.lock create mode 100644 yahia008/assignment_1/Scarb.toml create mode 100644 yahia008/assignment_1/src/assignment1.cairo create mode 100644 yahia008/assignment_1/src/lib.cairo diff --git a/yahia008/assignment_1/.gitignore b/yahia008/assignment_1/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/yahia008/assignment_1/.gitignore @@ -0,0 +1 @@ +target diff --git a/yahia008/assignment_1/Scarb.lock b/yahia008/assignment_1/Scarb.lock new file mode 100644 index 0000000..560210b --- /dev/null +++ b/yahia008/assignment_1/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "assignment_1" +version = "0.1.0" diff --git a/yahia008/assignment_1/Scarb.toml b/yahia008/assignment_1/Scarb.toml new file mode 100644 index 0000000..1b8c858 --- /dev/null +++ b/yahia008/assignment_1/Scarb.toml @@ -0,0 +1,14 @@ +[package] +name = "assignment_1" +version = "0.1.0" +edition = "2025_12" + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[executable] + +[cairo] +enable-gas = false + +[dependencies] +cairo_execute = "2.17.0" diff --git a/yahia008/assignment_1/src/assignment1.cairo b/yahia008/assignment_1/src/assignment1.cairo new file mode 100644 index 0000000..203821f --- /dev/null +++ b/yahia008/assignment_1/src/assignment1.cairo @@ -0,0 +1,62 @@ +use core::num::traits::CheckedMul; +use core::num::traits::CheckedAdd; +use core::num::traits::CheckedSub; + +#[derive(Drop)] +enum MathError { + Overflow, + DivisionByZero, + Underflow, +} + + +#[executable] +fn main() { + let add_result = add_number(10, 5); + match add_result { + Result::Ok(v) => println!("add value {}", v), + Result::Err(_) => println!("add error ", ), + }; + + let mul_result = multiply_number(10, 5); + match mul_result { + Result::Ok(v) => println!("mul value {}", v), + Result::Err(_) => println!("mul error"), + }; + + + let div_result = divide(10, 2); + match div_result { + Result::Ok(v) => println!("div value {}", v), + Result::Err(_) => println!("div error", ), + }; + + let sub_result = sub_num(10, 7); + match sub_result { + Result::Ok(v) => println!("sub value {}", v), + Result::Err(_) => println!("sub error"), + }; +} + + + +fn add_number(x: u128, y: u128) -> Result { + x.checked_add(y).ok_or(MathError::Overflow) +} + +fn multiply_number(x:u128, y:u128) -> Result { + x.checked_mul(y).ok_or(MathError::Overflow) +} + +fn divide(x: u128, y: u128) -> Result{ + if y == 0 { + return Result::Err(MathError::DivisionByZero); + } + + Result::Ok(x / y) +} + +fn sub_num(x:u128, y:u128) -> Result{ + x.checked_sub(y).ok_or(MathError::Underflow) +} + diff --git a/yahia008/assignment_1/src/lib.cairo b/yahia008/assignment_1/src/lib.cairo new file mode 100644 index 0000000..e45ed60 --- /dev/null +++ b/yahia008/assignment_1/src/lib.cairo @@ -0,0 +1 @@ +mod assignment1; From e6e2170358f52febb3a14acb26a07b08215f1425 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:12:02 +0000 Subject: [PATCH 2/9] assertion --- yahia008/assignment_1/src/assignment1.cairo | 20 +++++-- yahia008/assignment_2/.gitignore | 5 ++ yahia008/assignment_2/Scarb.lock | 24 +++++++++ yahia008/assignment_2/Scarb.toml | 52 +++++++++++++++++++ yahia008/assignment_2/snfoundry.toml | 11 ++++ yahia008/assignment_2/src/lib.cairo | 32 ++++++++++++ .../assignment_2/tests/test_contract.cairo | 47 +++++++++++++++++ 7 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 yahia008/assignment_2/.gitignore create mode 100644 yahia008/assignment_2/Scarb.lock create mode 100644 yahia008/assignment_2/Scarb.toml create mode 100644 yahia008/assignment_2/snfoundry.toml create mode 100644 yahia008/assignment_2/src/lib.cairo create mode 100644 yahia008/assignment_2/tests/test_contract.cairo diff --git a/yahia008/assignment_1/src/assignment1.cairo b/yahia008/assignment_1/src/assignment1.cairo index 203821f..588bba7 100644 --- a/yahia008/assignment_1/src/assignment1.cairo +++ b/yahia008/assignment_1/src/assignment1.cairo @@ -14,26 +14,38 @@ enum MathError { fn main() { let add_result = add_number(10, 5); match add_result { - Result::Ok(v) => println!("add value {}", v), + Result::Ok(v) => { + assert!(v==15, "assertion failed") + println!("add value {}", v) + }, Result::Err(_) => println!("add error ", ), }; let mul_result = multiply_number(10, 5); match mul_result { - Result::Ok(v) => println!("mul value {}", v), + Result::Ok(v) => { + assert!(v==50, "assertion failed") + println!("mul value {}", v) + }, Result::Err(_) => println!("mul error"), }; let div_result = divide(10, 2); match div_result { - Result::Ok(v) => println!("div value {}", v), + Result::Ok(v) => { + assert!(v==5, "assertion failed") + println!("div value {}", v) + }, Result::Err(_) => println!("div error", ), }; let sub_result = sub_num(10, 7); match sub_result { - Result::Ok(v) => println!("sub value {}", v), + Result::Ok(v) => { + assert!(v==3, "assertion failed") + println!("sub value {}", v) + }, Result::Err(_) => println!("sub error"), }; } diff --git a/yahia008/assignment_2/.gitignore b/yahia008/assignment_2/.gitignore new file mode 100644 index 0000000..4096f8b --- /dev/null +++ b/yahia008/assignment_2/.gitignore @@ -0,0 +1,5 @@ +target +.snfoundry_cache/ +snfoundry_trace/ +coverage/ +profile/ diff --git a/yahia008/assignment_2/Scarb.lock b/yahia008/assignment_2/Scarb.lock new file mode 100644 index 0000000..7c5aa84 --- /dev/null +++ b/yahia008/assignment_2/Scarb.lock @@ -0,0 +1,24 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "assignment_2" +version = "0.1.0" +dependencies = [ + "snforge_std", +] + +[[package]] +name = "snforge_scarb_plugin" +version = "0.59.0" +source = "registry+https://scarbs.xyz/" +checksum = "sha256:871fba677c03b66a1bf40815dac0ab1b385eb1b9be6e6c3cf2ad9788eeb2b6bb" + +[[package]] +name = "snforge_std" +version = "0.59.0" +source = "registry+https://scarbs.xyz/" +checksum = "sha256:3620924fa08bd2d740b2b5b01ef86c8dab3d4b9c2206387c8dbdc8d2ec15133e" +dependencies = [ + "snforge_scarb_plugin", +] diff --git a/yahia008/assignment_2/Scarb.toml b/yahia008/assignment_2/Scarb.toml new file mode 100644 index 0000000..4eb7af4 --- /dev/null +++ b/yahia008/assignment_2/Scarb.toml @@ -0,0 +1,52 @@ +[package] +name = "assignment_2" +version = "0.1.0" +edition = "2024_07" + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[dependencies] +starknet = "2.17.0" + +[dev-dependencies] +snforge_std = "0.59.0" +assert_macros = "2.17.0" + +[[target.starknet-contract]] +sierra = true + +[scripts] +test = "snforge test" + +[tool.scarb] +allow-prebuilt-plugins = ["snforge_std"] + +# Visit https://foundry-rs.github.io/starknet-foundry/appendix/scarb-toml.html for more information + +# [tool.snforge] # Define `snforge` tool section +# exit_first = true # Stop tests execution immediately upon the first failure +# fuzzer_runs = 1234 # Number of runs of the random fuzzer +# fuzzer_seed = 1111 # Seed for the random fuzzer + +# [[tool.snforge.fork]] # Used for fork testing +# name = "SOME_NAME" # Fork name +# url = "http://your.rpc.url" # Url of the RPC provider +# block_id.tag = "latest" # Block to fork from (block tag) + +# [[tool.snforge.fork]] +# name = "SOME_SECOND_NAME" +# url = "http://your.second.rpc.url" +# block_id.number = "123" # Block to fork from (block number) + +# [[tool.snforge.fork]] +# name = "SOME_THIRD_NAME" +# url = "http://your.third.rpc.url" +# block_id.hash = "0x123" # Block to fork from (block hash) + +# [profile.dev.cairo] # Configure Cairo compiler +# unstable-add-statements-code-locations-debug-info = true # Should be used if you want to use coverage +# unstable-add-statements-functions-debug-info = true # Should be used if you want to use coverage/profiler +# inlining-strategy = "avoid" # Should be used if you want to use coverage + +# [features] # Used for conditional compilation +# enable_for_tests = [] # Feature name and list of other features that should be enabled with it diff --git a/yahia008/assignment_2/snfoundry.toml b/yahia008/assignment_2/snfoundry.toml new file mode 100644 index 0000000..686c2ab --- /dev/null +++ b/yahia008/assignment_2/snfoundry.toml @@ -0,0 +1,11 @@ +# Visit https://foundry-rs.github.io/starknet-foundry/appendix/snfoundry-toml.html +# and https://foundry-rs.github.io/starknet-foundry/projects/configuration.html for more information + +# [sncast.default] # Define a profile name +# url = "https://api.zan.top/public/starknet-sepolia/rpc/v0_10" # Url of the RPC provider +# accounts-file = "../account-file" # Path to the file with the account data +# account = "mainuser" # Account from `accounts_file` or default account file that will be used for the transactions +# keystore = "~/keystore" # Path to the keystore file +# wait-params = { timeout = 300, retry-interval = 10 } # Wait for submitted transaction parameters +# block-explorer = "Voyager" # Block explorer service used to display links to transaction details +# show-explorer-links = true # Print links pointing to pages with transaction details in the chosen block explorer diff --git a/yahia008/assignment_2/src/lib.cairo b/yahia008/assignment_2/src/lib.cairo new file mode 100644 index 0000000..9a718e3 --- /dev/null +++ b/yahia008/assignment_2/src/lib.cairo @@ -0,0 +1,32 @@ +/// Interface representing `HelloContract`. +/// This interface allows modification and retrieval of the contract balance. +#[starknet::interface] +pub trait IHelloStarknet { + /// Increase contract balance. + fn increase_balance(ref self: TContractState, amount: felt252); + /// Retrieve contract balance. + fn get_balance(self: @TContractState) -> felt252; +} + +/// Simple contract for managing balance. +#[starknet::contract] +mod HelloStarknet { + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + + #[storage] + struct Storage { + balance: felt252, + } + + #[abi(embed_v0)] + impl HelloStarknetImpl of super::IHelloStarknet { + fn increase_balance(ref self: ContractState, amount: felt252) { + assert(amount != 0, 'Amount cannot be 0'); + self.balance.write(self.balance.read() + amount); + } + + fn get_balance(self: @ContractState) -> felt252 { + self.balance.read() + } + } +} diff --git a/yahia008/assignment_2/tests/test_contract.cairo b/yahia008/assignment_2/tests/test_contract.cairo new file mode 100644 index 0000000..1961e75 --- /dev/null +++ b/yahia008/assignment_2/tests/test_contract.cairo @@ -0,0 +1,47 @@ +use starknet::ContractAddress; + +use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; + +use assignment_2::IHelloStarknetSafeDispatcher; +use assignment_2::IHelloStarknetSafeDispatcherTrait; +use assignment_2::IHelloStarknetDispatcher; +use assignment_2::IHelloStarknetDispatcherTrait; + +fn deploy_contract(name: ByteArray) -> ContractAddress { + let contract = declare(name).unwrap().contract_class(); + let (contract_address, _) = contract.deploy(@ArrayTrait::new()).unwrap(); + contract_address +} + +#[test] +fn test_increase_balance() { + let contract_address = deploy_contract("HelloStarknet"); + + let dispatcher = IHelloStarknetDispatcher { contract_address }; + + let balance_before = dispatcher.get_balance(); + assert(balance_before == 0, 'Invalid balance'); + + dispatcher.increase_balance(42); + + let balance_after = dispatcher.get_balance(); + assert(balance_after == 42, 'Invalid balance'); +} + +#[test] +#[feature("safe_dispatcher")] +fn test_cannot_increase_balance_with_zero_value() { + let contract_address = deploy_contract("HelloStarknet"); + + let safe_dispatcher = IHelloStarknetSafeDispatcher { contract_address }; + + let balance_before = safe_dispatcher.get_balance().unwrap(); + assert(balance_before == 0, 'Invalid balance'); + + match safe_dispatcher.increase_balance(0) { + Result::Ok(_) => core::panic_with_felt252('Should have panicked'), + Result::Err(panic_data) => { + assert(*panic_data.at(0) == 'Amount cannot be 0', *panic_data.at(0)); + } + }; +} From 94556a48a2e44deaa80103488a6a8740cf5684c3 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:59:14 +0000 Subject: [PATCH 3/9] contract on progress --- yahia008/assignment_2/src/lib.cairo | 44 ++++++++--------- .../assignment_2/tests/test_contract.cairo | 47 ------------------- 2 files changed, 20 insertions(+), 71 deletions(-) delete mode 100644 yahia008/assignment_2/tests/test_contract.cairo diff --git a/yahia008/assignment_2/src/lib.cairo b/yahia008/assignment_2/src/lib.cairo index 9a718e3..476eb93 100644 --- a/yahia008/assignment_2/src/lib.cairo +++ b/yahia008/assignment_2/src/lib.cairo @@ -1,32 +1,28 @@ -/// Interface representing `HelloContract`. -/// This interface allows modification and retrieval of the contract balance. +use starknet::{ContractAddress, get_caller_address}; #[starknet::interface] -pub trait IHelloStarknet { - /// Increase contract balance. - fn increase_balance(ref self: TContractState, amount: felt252); - /// Retrieve contract balance. - fn get_balance(self: @TContractState) -> felt252; +pub trait ICounter { + fn increase_count(ref self: T, amount: u32); + fn transfer_ownership(ref self: T, new_owner: ContractAddress); + fn get_count(self: @T) -> u32; + fn get_owner(self: @T) -> ContractAddress; + } -/// Simple contract for managing balance. #[starknet::contract] -mod HelloStarknet { - use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; +mod CounterV2{ + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - #[storage] - struct Storage { - balance: felt252, - } + use super::ICounter; + use starknet::ContractAddress; - #[abi(embed_v0)] - impl HelloStarknetImpl of super::IHelloStarknet { - fn increase_balance(ref self: ContractState, amount: felt252) { - assert(amount != 0, 'Amount cannot be 0'); - self.balance.write(self.balance.read() + amount); - } + #[storage] + struct Storage{ + count:u32, + owner:ContractAddress + } - fn get_balance(self: @ContractState) -> felt252 { - self.balance.read() - } + #[constructor] + fn constructor(ref self:ContractState, initial_owner:ContractAddress){ + self.owner.write(initial_owner); } -} +} \ No newline at end of file diff --git a/yahia008/assignment_2/tests/test_contract.cairo b/yahia008/assignment_2/tests/test_contract.cairo deleted file mode 100644 index 1961e75..0000000 --- a/yahia008/assignment_2/tests/test_contract.cairo +++ /dev/null @@ -1,47 +0,0 @@ -use starknet::ContractAddress; - -use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; - -use assignment_2::IHelloStarknetSafeDispatcher; -use assignment_2::IHelloStarknetSafeDispatcherTrait; -use assignment_2::IHelloStarknetDispatcher; -use assignment_2::IHelloStarknetDispatcherTrait; - -fn deploy_contract(name: ByteArray) -> ContractAddress { - let contract = declare(name).unwrap().contract_class(); - let (contract_address, _) = contract.deploy(@ArrayTrait::new()).unwrap(); - contract_address -} - -#[test] -fn test_increase_balance() { - let contract_address = deploy_contract("HelloStarknet"); - - let dispatcher = IHelloStarknetDispatcher { contract_address }; - - let balance_before = dispatcher.get_balance(); - assert(balance_before == 0, 'Invalid balance'); - - dispatcher.increase_balance(42); - - let balance_after = dispatcher.get_balance(); - assert(balance_after == 42, 'Invalid balance'); -} - -#[test] -#[feature("safe_dispatcher")] -fn test_cannot_increase_balance_with_zero_value() { - let contract_address = deploy_contract("HelloStarknet"); - - let safe_dispatcher = IHelloStarknetSafeDispatcher { contract_address }; - - let balance_before = safe_dispatcher.get_balance().unwrap(); - assert(balance_before == 0, 'Invalid balance'); - - match safe_dispatcher.increase_balance(0) { - Result::Ok(_) => core::panic_with_felt252('Should have panicked'), - Result::Err(panic_data) => { - assert(*panic_data.at(0) == 'Amount cannot be 0', *panic_data.at(0)); - } - }; -} From 062cb3e69884252fb4cabcbffefa4210e03035fc Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Wed, 29 Apr 2026 00:00:23 +0000 Subject: [PATCH 4/9] contract build successfully --- yahia008/assignment_2/src/lib.cairo | 61 ++++++++++++++++++++++--- yahia008/assignment_2/src/mylogic.cairo | 16 +++++++ 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 yahia008/assignment_2/src/mylogic.cairo diff --git a/yahia008/assignment_2/src/lib.cairo b/yahia008/assignment_2/src/lib.cairo index 476eb93..f177898 100644 --- a/yahia008/assignment_2/src/lib.cairo +++ b/yahia008/assignment_2/src/lib.cairo @@ -1,28 +1,77 @@ -use starknet::{ContractAddress, get_caller_address}; +mod mylogic; +use starknet::{ContractAddress}; #[starknet::interface] pub trait ICounter { - fn increase_count(ref self: T, amount: u32); - fn transfer_ownership(ref self: T, new_owner: ContractAddress); - fn get_count(self: @T) -> u32; + fn get_count(self: @T) -> u128; fn get_owner(self: @T) -> ContractAddress; + fn transfer_ownership(ref self: T, new_owner: ContractAddress); + fn increase_count(ref self: T, amount: u128); + fn decrease_count (ref self:T, amount:u128); + fn reset_count(ref self:T); + + } #[starknet::contract] mod CounterV2{ - use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + use crate::mylogic; +use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; use super::ICounter; use starknet::ContractAddress; + use starknet::get_caller_address; + #[storage] struct Storage{ - count:u32, + count:u128, owner:ContractAddress } #[constructor] fn constructor(ref self:ContractState, initial_owner:ContractAddress){ self.owner.write(initial_owner); + self.count.write(0); } + + #[abi(embed_v0)] + impl ICounterimpl of ICounter { + + fn get_count(self: @ContractState) -> u128 { + self.count.read() + } + fn get_owner(self: @ContractState) -> ContractAddress{ + self.owner.read() + } + fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can transfer"); + self.owner.write(new_owner); + } + fn increase_count(ref self: ContractState, amount: u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::increase_count(current, amount); + self.count.write(new); + } + fn decrease_count (ref self:ContractState, amount:u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::decrease_count(current, amount); + self.count.write(new); + } + fn reset_count(ref self:ContractState){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + let new:u128 = mylogic::reset_count(); + self.count.write(new); + + + } + } } \ No newline at end of file diff --git a/yahia008/assignment_2/src/mylogic.cairo b/yahia008/assignment_2/src/mylogic.cairo new file mode 100644 index 0000000..a411d43 --- /dev/null +++ b/yahia008/assignment_2/src/mylogic.cairo @@ -0,0 +1,16 @@ +use core::num::traits::CheckedAdd; +use core::num::traits::CheckedSub; + + + +pub fn increase_count(current: u128, amount: u128) -> u128{ + current.checked_add(amount).expect('overflow') +} + +pub fn decrease_count(current: u128, amount: u128) -> u128 { + current.checked_sub(amount).expect('underflow') +} + +pub fn reset_count() -> u128 { + 0 +} \ No newline at end of file From 4e224871bc84e8f0ef6e471dedf19a9432f78edf Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Wed, 29 Apr 2026 12:21:04 +0000 Subject: [PATCH 5/9] update --- yahia008/assignment_1/src/assignment1.cairo | 4 ++-- yahia008/assignment_2/src/mylogic.cairo | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yahia008/assignment_1/src/assignment1.cairo b/yahia008/assignment_1/src/assignment1.cairo index 588bba7..12e2a8c 100644 --- a/yahia008/assignment_1/src/assignment1.cairo +++ b/yahia008/assignment_1/src/assignment1.cairo @@ -12,10 +12,10 @@ enum MathError { #[executable] fn main() { - let add_result = add_number(10, 5); + let add_result = add_number(0, 0); match add_result { Result::Ok(v) => { - assert!(v==15, "assertion failed") + assert!(v==0, "assertion failed") println!("add value {}", v) }, Result::Err(_) => println!("add error ", ), diff --git a/yahia008/assignment_2/src/mylogic.cairo b/yahia008/assignment_2/src/mylogic.cairo index a411d43..e716f0a 100644 --- a/yahia008/assignment_2/src/mylogic.cairo +++ b/yahia008/assignment_2/src/mylogic.cairo @@ -4,10 +4,18 @@ use core::num::traits::CheckedSub; pub fn increase_count(current: u128, amount: u128) -> u128{ + if amount == 0 + { + return current; + } current.checked_add(amount).expect('overflow') } pub fn decrease_count(current: u128, amount: u128) -> u128 { + if amount == 0 + { + return current; + } current.checked_sub(amount).expect('underflow') } From 34590c4a75714cf287c0f7bf3d461aec0a633fd3 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:30:40 +0000 Subject: [PATCH 6/9] module --- yahia008/av2_pro/arithmetic_logic/.gitignore | 1 + yahia008/av2_pro/arithmetic_logic/Scarb.lock | 6 ++ yahia008/av2_pro/arithmetic_logic/Scarb.toml | 19 +++++ .../av2_pro/arithmetic_logic/src/lib.cairo | 1 + .../arithmetic_logic/src/mylogic.cairo | 43 +++++++++++ yahia008/av2_pro/counterv2_pro/.gitignore | 5 ++ yahia008/av2_pro/counterv2_pro/Scarb.lock | 29 +++++++ yahia008/av2_pro/counterv2_pro/Scarb.toml | 53 +++++++++++++ yahia008/av2_pro/counterv2_pro/snfoundry.toml | 11 +++ yahia008/av2_pro/counterv2_pro/src/lib.cairo | 75 +++++++++++++++++++ yahia008/av2_pro/use_arithmetic/.gitignore | 1 + yahia008/av2_pro/use_arithmetic/Scarb.lock | 13 ++++ yahia008/av2_pro/use_arithmetic/Scarb.toml | 15 ++++ .../use_arithmetic/src/hello_world.cairo | 31 ++++++++ yahia008/av2_pro/use_arithmetic/src/lib.cairo | 1 + 15 files changed, 304 insertions(+) create mode 100644 yahia008/av2_pro/arithmetic_logic/.gitignore create mode 100644 yahia008/av2_pro/arithmetic_logic/Scarb.lock create mode 100644 yahia008/av2_pro/arithmetic_logic/Scarb.toml create mode 100644 yahia008/av2_pro/arithmetic_logic/src/lib.cairo create mode 100644 yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo create mode 100644 yahia008/av2_pro/counterv2_pro/.gitignore create mode 100644 yahia008/av2_pro/counterv2_pro/Scarb.lock create mode 100644 yahia008/av2_pro/counterv2_pro/Scarb.toml create mode 100644 yahia008/av2_pro/counterv2_pro/snfoundry.toml create mode 100644 yahia008/av2_pro/counterv2_pro/src/lib.cairo create mode 100644 yahia008/av2_pro/use_arithmetic/.gitignore create mode 100644 yahia008/av2_pro/use_arithmetic/Scarb.lock create mode 100644 yahia008/av2_pro/use_arithmetic/Scarb.toml create mode 100644 yahia008/av2_pro/use_arithmetic/src/hello_world.cairo create mode 100644 yahia008/av2_pro/use_arithmetic/src/lib.cairo diff --git a/yahia008/av2_pro/arithmetic_logic/.gitignore b/yahia008/av2_pro/arithmetic_logic/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/.gitignore @@ -0,0 +1 @@ +target diff --git a/yahia008/av2_pro/arithmetic_logic/Scarb.lock b/yahia008/av2_pro/arithmetic_logic/Scarb.lock new file mode 100644 index 0000000..f50718d --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "arithmetic_logic" +version = "0.1.0" diff --git a/yahia008/av2_pro/arithmetic_logic/Scarb.toml b/yahia008/av2_pro/arithmetic_logic/Scarb.toml new file mode 100644 index 0000000..6e598c9 --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/Scarb.toml @@ -0,0 +1,19 @@ +[package] +name = "arithmetic_logic" +version = "0.1.0" +edition = "2025_12" + + +[lib] +sierra = true + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[executable] + +[cairo] +enable-gas = false + +[dependencies] +cairo_execute = "2.17.0" + diff --git a/yahia008/av2_pro/arithmetic_logic/src/lib.cairo b/yahia008/av2_pro/arithmetic_logic/src/lib.cairo new file mode 100644 index 0000000..7fa7860 --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/src/lib.cairo @@ -0,0 +1 @@ +pub mod mylogic; \ No newline at end of file diff --git a/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo b/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo new file mode 100644 index 0000000..b6dd43a --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo @@ -0,0 +1,43 @@ +use core::num::traits::CheckedAdd; +use core::num::traits::CheckedSub; +use core::num::traits::CheckedMul; + +#[derive(Drop)] +enum MathError { + Overflow, + DivisionByZero, + Underflow, +} + + +pub fn add_num(x: u128, y: u128) -> u128{ + if y == 0 + { + return x; + } + x.checked_add(y).expect('overflow') +} + +pub fn sub_num(x: u128, y: u128) -> u128 { + if y == 0 + { + return x; + } + x.checked_sub(y).expect('underflow') +} + +pub fn multiply_number(x:u128, y:u128) -> Result { + x.checked_mul(y).ok_or(MathError::Overflow) +} + +pub fn divide(x: u128, y: u128) -> Result{ + if y == 0 { + return Result::Err(MathError::DivisionByZero); + } + + Result::Ok(x / y) +} + +pub fn reset_count() -> u128 { + 0 +} \ No newline at end of file diff --git a/yahia008/av2_pro/counterv2_pro/.gitignore b/yahia008/av2_pro/counterv2_pro/.gitignore new file mode 100644 index 0000000..4096f8b --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/.gitignore @@ -0,0 +1,5 @@ +target +.snfoundry_cache/ +snfoundry_trace/ +coverage/ +profile/ diff --git a/yahia008/av2_pro/counterv2_pro/Scarb.lock b/yahia008/av2_pro/counterv2_pro/Scarb.lock new file mode 100644 index 0000000..bcc4c05 --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/Scarb.lock @@ -0,0 +1,29 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "arithmetic_logic" +version = "0.1.0" + +[[package]] +name = "counterv2_pro" +version = "0.1.0" +dependencies = [ + "arithmetic_logic", + "snforge_std", +] + +[[package]] +name = "snforge_scarb_plugin" +version = "0.59.0" +source = "registry+https://scarbs.xyz/" +checksum = "sha256:871fba677c03b66a1bf40815dac0ab1b385eb1b9be6e6c3cf2ad9788eeb2b6bb" + +[[package]] +name = "snforge_std" +version = "0.59.0" +source = "registry+https://scarbs.xyz/" +checksum = "sha256:3620924fa08bd2d740b2b5b01ef86c8dab3d4b9c2206387c8dbdc8d2ec15133e" +dependencies = [ + "snforge_scarb_plugin", +] diff --git a/yahia008/av2_pro/counterv2_pro/Scarb.toml b/yahia008/av2_pro/counterv2_pro/Scarb.toml new file mode 100644 index 0000000..059e06e --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/Scarb.toml @@ -0,0 +1,53 @@ +[package] +name = "counterv2_pro" +version = "0.1.0" +edition = "2024_07" + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[dependencies] +starknet = "2.17.0" +arithmetic_logic = {path = "../arithmetic_logic"} + +[dev-dependencies] +snforge_std = "0.59.0" +assert_macros = "2.17.0" + +[[target.starknet-contract]] +sierra = true + +[scripts] +test = "snforge test" + +[tool.scarb] +allow-prebuilt-plugins = ["snforge_std"] + +# Visit https://foundry-rs.github.io/starknet-foundry/appendix/scarb-toml.html for more information + +# [tool.snforge] # Define `snforge` tool section +# exit_first = true # Stop tests execution immediately upon the first failure +# fuzzer_runs = 1234 # Number of runs of the random fuzzer +# fuzzer_seed = 1111 # Seed for the random fuzzer + +# [[tool.snforge.fork]] # Used for fork testing +# name = "SOME_NAME" # Fork name +# url = "http://your.rpc.url" # Url of the RPC provider +# block_id.tag = "latest" # Block to fork from (block tag) + +# [[tool.snforge.fork]] +# name = "SOME_SECOND_NAME" +# url = "http://your.second.rpc.url" +# block_id.number = "123" # Block to fork from (block number) + +# [[tool.snforge.fork]] +# name = "SOME_THIRD_NAME" +# url = "http://your.third.rpc.url" +# block_id.hash = "0x123" # Block to fork from (block hash) + +# [profile.dev.cairo] # Configure Cairo compiler +# unstable-add-statements-code-locations-debug-info = true # Should be used if you want to use coverage +# unstable-add-statements-functions-debug-info = true # Should be used if you want to use coverage/profiler +# inlining-strategy = "avoid" # Should be used if you want to use coverage + +# [features] # Used for conditional compilation +# enable_for_tests = [] # Feature name and list of other features that should be enabled with it diff --git a/yahia008/av2_pro/counterv2_pro/snfoundry.toml b/yahia008/av2_pro/counterv2_pro/snfoundry.toml new file mode 100644 index 0000000..686c2ab --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/snfoundry.toml @@ -0,0 +1,11 @@ +# Visit https://foundry-rs.github.io/starknet-foundry/appendix/snfoundry-toml.html +# and https://foundry-rs.github.io/starknet-foundry/projects/configuration.html for more information + +# [sncast.default] # Define a profile name +# url = "https://api.zan.top/public/starknet-sepolia/rpc/v0_10" # Url of the RPC provider +# accounts-file = "../account-file" # Path to the file with the account data +# account = "mainuser" # Account from `accounts_file` or default account file that will be used for the transactions +# keystore = "~/keystore" # Path to the keystore file +# wait-params = { timeout = 300, retry-interval = 10 } # Wait for submitted transaction parameters +# block-explorer = "Voyager" # Block explorer service used to display links to transaction details +# show-explorer-links = true # Print links pointing to pages with transaction details in the chosen block explorer diff --git a/yahia008/av2_pro/counterv2_pro/src/lib.cairo b/yahia008/av2_pro/counterv2_pro/src/lib.cairo new file mode 100644 index 0000000..9b757f5 --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/src/lib.cairo @@ -0,0 +1,75 @@ +use arithmetic_logic::mylogic; +use starknet::{ContractAddress}; +#[starknet::interface] +pub trait ICounter { + fn get_count(self: @T) -> u128; + fn get_owner(self: @T) -> ContractAddress; + fn transfer_ownership(ref self: T, new_owner: ContractAddress); + fn increase_count(ref self: T, amount: u128); + fn decrease_count (ref self:T, amount:u128); + fn reset_count(ref self:T); + + + +} + +#[starknet::contract] +mod CounterV2{ + use crate::mylogic; +use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + + use super::ICounter; + use starknet::ContractAddress; + use starknet::get_caller_address; + + + #[storage] + struct Storage{ + count:u128, + owner:ContractAddress + } + + #[constructor] + fn constructor(ref self:ContractState, initial_owner:ContractAddress){ + self.owner.write(initial_owner); + self.count.write(0); + } + + #[abi(embed_v0)] + impl ICounterimpl of ICounter { + + fn get_count(self: @ContractState) -> u128 { + self.count.read() + } + fn get_owner(self: @ContractState) -> ContractAddress{ + self.owner.read() + } + fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can transfer"); + self.owner.write(new_owner); + } + fn increase_count(ref self: ContractState, amount: u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::add_num(current, amount); + self.count.write(new); + } + fn decrease_count (ref self:ContractState, amount:u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::sub_num(current, amount); + self.count.write(new); + } + fn reset_count(ref self:ContractState){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + let new:u128 = mylogic::reset_count(); + self.count.write(new); + } + } +} \ No newline at end of file diff --git a/yahia008/av2_pro/use_arithmetic/.gitignore b/yahia008/av2_pro/use_arithmetic/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/yahia008/av2_pro/use_arithmetic/.gitignore @@ -0,0 +1 @@ +target diff --git a/yahia008/av2_pro/use_arithmetic/Scarb.lock b/yahia008/av2_pro/use_arithmetic/Scarb.lock new file mode 100644 index 0000000..c8d9a3c --- /dev/null +++ b/yahia008/av2_pro/use_arithmetic/Scarb.lock @@ -0,0 +1,13 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "arithmetic_logic" +version = "0.1.0" + +[[package]] +name = "use_arithmetic" +version = "0.1.0" +dependencies = [ + "arithmetic_logic", +] diff --git a/yahia008/av2_pro/use_arithmetic/Scarb.toml b/yahia008/av2_pro/use_arithmetic/Scarb.toml new file mode 100644 index 0000000..3fdc2ec --- /dev/null +++ b/yahia008/av2_pro/use_arithmetic/Scarb.toml @@ -0,0 +1,15 @@ +[package] +name = "use_arithmetic" +version = "0.1.0" +edition = "2025_12" + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[executable] + +[cairo] +enable-gas = false + +[dependencies] +cairo_execute = "2.17.0" +arithmetic_logic = {path = "../arithmetic_logic"} diff --git a/yahia008/av2_pro/use_arithmetic/src/hello_world.cairo b/yahia008/av2_pro/use_arithmetic/src/hello_world.cairo new file mode 100644 index 0000000..437ca78 --- /dev/null +++ b/yahia008/av2_pro/use_arithmetic/src/hello_world.cairo @@ -0,0 +1,31 @@ +use arithmetic_logic::mylogic; +#[executable] + +fn main() { + + let add_result = mylogic::add_num(10, 5); + assert!(add_result == 15, "result must be 15 "); + + let sub_result = mylogic::sub_num(10, 5); + assert!(sub_result == 5, "result mudt be 5"); + + let mul_result = mylogic::multiply_number(10, 5); + match mul_result { + Result::Ok(v) => { + assert!(v==50, "assertion failed") + println!("mul value {}", v) + }, + Result::Err(_) => println!("mul error"), + }; + + + let div_result = mylogic::divide(10, 2); + match div_result { + Result::Ok(v) => { + assert!(v==5, "assertion failed") + println!("div value {}", v) + }, + Result::Err(_) => println!("div error", ), + }; + +} diff --git a/yahia008/av2_pro/use_arithmetic/src/lib.cairo b/yahia008/av2_pro/use_arithmetic/src/lib.cairo new file mode 100644 index 0000000..e5eb338 --- /dev/null +++ b/yahia008/av2_pro/use_arithmetic/src/lib.cairo @@ -0,0 +1 @@ +mod hello_world; From b870e5669d814365d2cdc6ebae9316fcbaab3b59 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:50:19 +0000 Subject: [PATCH 7/9] change --- yahia008/av2_pro/counterv2_pro/src/lib.cairo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yahia008/av2_pro/counterv2_pro/src/lib.cairo b/yahia008/av2_pro/counterv2_pro/src/lib.cairo index 9b757f5..6d02c9b 100644 --- a/yahia008/av2_pro/counterv2_pro/src/lib.cairo +++ b/yahia008/av2_pro/counterv2_pro/src/lib.cairo @@ -15,13 +15,13 @@ pub trait ICounter { #[starknet::contract] mod CounterV2{ - use crate::mylogic; + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; use super::ICounter; use starknet::ContractAddress; use starknet::get_caller_address; - + use super::mylogic; #[storage] struct Storage{ From fa7c1c32ace659c07abe92b9476da75a8d841c99 Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:08:52 +0000 Subject: [PATCH 8/9] jst little refining --- yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo | 3 +++ yahia008/av2_pro/counterv2_pro/src/lib.cairo | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo b/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo index b6dd43a..b91c594 100644 --- a/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo +++ b/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo @@ -27,6 +27,9 @@ pub fn sub_num(x: u128, y: u128) -> u128 { } pub fn multiply_number(x:u128, y:u128) -> Result { + if x == 0 || y == 0 { + return Result::Ok(0); + } x.checked_mul(y).ok_or(MathError::Overflow) } diff --git a/yahia008/av2_pro/counterv2_pro/src/lib.cairo b/yahia008/av2_pro/counterv2_pro/src/lib.cairo index 6d02c9b..ea88953 100644 --- a/yahia008/av2_pro/counterv2_pro/src/lib.cairo +++ b/yahia008/av2_pro/counterv2_pro/src/lib.cairo @@ -7,10 +7,7 @@ pub trait ICounter { fn transfer_ownership(ref self: T, new_owner: ContractAddress); fn increase_count(ref self: T, amount: u128); fn decrease_count (ref self:T, amount:u128); - fn reset_count(ref self:T); - - - + fn reset_count(ref self:T); } #[starknet::contract] From 01a009fc1cdd6483fd82d0881a80d12d60f606fe Mon Sep 17 00:00:00 2001 From: yahia008 <120284117+yahia008@users.noreply.github.com> Date: Sun, 10 May 2026 23:21:21 +0000 Subject: [PATCH 9/9] test --- .../av2_pro/counterv2_pro/src/counter.cairo | 76 ++++++ yahia008/av2_pro/counterv2_pro/src/lib.cairo | 76 +----- .../counterv2_pro/tests/test_couter.cairo | 236 ++++++++++++++++++ 3 files changed, 316 insertions(+), 72 deletions(-) create mode 100644 yahia008/av2_pro/counterv2_pro/src/counter.cairo create mode 100644 yahia008/av2_pro/counterv2_pro/tests/test_couter.cairo diff --git a/yahia008/av2_pro/counterv2_pro/src/counter.cairo b/yahia008/av2_pro/counterv2_pro/src/counter.cairo new file mode 100644 index 0000000..7d9c225 --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/src/counter.cairo @@ -0,0 +1,76 @@ +use arithmetic_logic::mylogic; +use starknet::{ContractAddress}; +#[starknet::interface] +pub trait ICounter { + fn get_count(self: @T) -> u128; + fn get_owner(self: @T) -> ContractAddress; + fn transfer_ownership(ref self: T, new_owner: ContractAddress); + fn increase_count(ref self: T, amount: u128); + fn decrease_count (ref self:T, amount:u128); + fn reset_count(ref self:T); +} + +#[starknet::contract] +pub mod CounterV2{ + +use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + + use super::ICounter; + use starknet::ContractAddress; + use starknet::get_caller_address; + use super::mylogic; + + #[storage] + struct Storage{ + count:u128, + owner:ContractAddress + } + + #[constructor] + fn constructor(ref self:ContractState, initial_owner:ContractAddress){ + self.owner.write(initial_owner); + self.count.write(0); + } + + #[abi(embed_v0)] + impl ICounterimpl of ICounter { + + fn get_count(self: @ContractState) -> u128 { + self.count.read() + } + fn get_owner(self: @ContractState) -> ContractAddress{ + self.owner.read() + } + fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can transfer"); + self.owner.write(new_owner); + } + fn increase_count(ref self: ContractState, amount: u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::add_num(current, amount); + self.count.write(new); + } + fn decrease_count (ref self:ContractState, amount:u128){ + let caller:ContractAddress = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + + let current = self.count.read(); + let new:u128 = mylogic::sub_num(current, amount); + self.count.write(new); + } + fn reset_count(ref self:ContractState){ + let caller = get_caller_address(); + assert!(caller == self.owner.read(), "Only owner can change state"); + let current= self.count.read(); + if current != 0 { + let new:u128 = mylogic::reset_count(); + self.count.write(new); + } + // emit it already zero + } + } +} \ No newline at end of file diff --git a/yahia008/av2_pro/counterv2_pro/src/lib.cairo b/yahia008/av2_pro/counterv2_pro/src/lib.cairo index ea88953..22bde39 100644 --- a/yahia008/av2_pro/counterv2_pro/src/lib.cairo +++ b/yahia008/av2_pro/counterv2_pro/src/lib.cairo @@ -1,72 +1,4 @@ -use arithmetic_logic::mylogic; -use starknet::{ContractAddress}; -#[starknet::interface] -pub trait ICounter { - fn get_count(self: @T) -> u128; - fn get_owner(self: @T) -> ContractAddress; - fn transfer_ownership(ref self: T, new_owner: ContractAddress); - fn increase_count(ref self: T, amount: u128); - fn decrease_count (ref self:T, amount:u128); - fn reset_count(ref self:T); -} - -#[starknet::contract] -mod CounterV2{ - -use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - - use super::ICounter; - use starknet::ContractAddress; - use starknet::get_caller_address; - use super::mylogic; - - #[storage] - struct Storage{ - count:u128, - owner:ContractAddress - } - - #[constructor] - fn constructor(ref self:ContractState, initial_owner:ContractAddress){ - self.owner.write(initial_owner); - self.count.write(0); - } - - #[abi(embed_v0)] - impl ICounterimpl of ICounter { - - fn get_count(self: @ContractState) -> u128 { - self.count.read() - } - fn get_owner(self: @ContractState) -> ContractAddress{ - self.owner.read() - } - fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress){ - let caller = get_caller_address(); - assert!(caller == self.owner.read(), "Only owner can transfer"); - self.owner.write(new_owner); - } - fn increase_count(ref self: ContractState, amount: u128){ - let caller:ContractAddress = get_caller_address(); - assert!(caller == self.owner.read(), "Only owner can change state"); - - let current = self.count.read(); - let new:u128 = mylogic::add_num(current, amount); - self.count.write(new); - } - fn decrease_count (ref self:ContractState, amount:u128){ - let caller:ContractAddress = get_caller_address(); - assert!(caller == self.owner.read(), "Only owner can change state"); - - let current = self.count.read(); - let new:u128 = mylogic::sub_num(current, amount); - self.count.write(new); - } - fn reset_count(ref self:ContractState){ - let caller = get_caller_address(); - assert!(caller == self.owner.read(), "Only owner can change state"); - let new:u128 = mylogic::reset_count(); - self.count.write(new); - } - } -} \ No newline at end of file +mod counter; +pub use counter::CounterV2; +pub use counter::ICounterDispatcher; +pub use counter::ICounterDispatcherTrait; \ No newline at end of file diff --git a/yahia008/av2_pro/counterv2_pro/tests/test_couter.cairo b/yahia008/av2_pro/counterv2_pro/tests/test_couter.cairo new file mode 100644 index 0000000..84f1c32 --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/tests/test_couter.cairo @@ -0,0 +1,236 @@ +use starknet::SyscallResultTrait; +use snforge_std::DeclareResultTrait; +use counterv2_pro::CounterV2; +use starknet::testing::{ + set_contract_address, set_caller_address +}; +use snforge_std::{declare, ContractClassTrait, start_cheat_caller_address, }; +use counterv2_pro::{ICounterDispatcher, ICounterDispatcherTrait}; +use starknet::syscalls::deploy_syscall; +use starknet::ContractAddress; +use starknet::contract_address_const; + +const U128_MAX: u128 = 340282366920938463463374607431768211455; + + fn owner() -> ContractAddress { + + contract_address_const::<0x1>() + } + + fn attacker() -> ContractAddress { + contract_address_const::<0x2>() + } + + fn new_owner() -> ContractAddress { + contract_address_const::<0x3>() + } + +fn deploy_contract(initial_owner: ContractAddress) -> ICounterDispatcher { + let contract = declare("CounterV2").unwrap_syscall().contract_class(); + + let mut calldata = array![initial_owner.into()]; + + let (contract_address, _) = contract.deploy(@calldata).unwrap_syscall(); + + ICounterDispatcher { contract_address } +} + +#[cfg(test)] +mod tests { + use super::*; + + use super::new_owner; +use counterv2_pro::ICounterDispatcherTrait; +use snforge_std::start_cheat_caller_address; +use super::deploy_contract; +use super::attacker; +use super::owner; +use starknet::SyscallResultTrait; + #[test] + fn test_constructor(){ + let initial_owner = owner(); + let counter = deploy_contract(initial_owner); + assert!(counter.get_count() == 0, "initial count should be zero") + assert!(counter.get_owner() == initial_owner, "owner is initial owner"); + } + + #[test] + fn test_increase_count() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + + counter.increase_count(5); + assert_eq!(counter.get_count(), 5); + + counter.increase_count(3); + assert_eq!(counter.get_count(), 8); + } + + #[test] + #[should_panic(expected: "Only owner can change state")] + fn test_increase_count_not_owner() { + let owner = owner(); + let counter = deploy_contract(owner); + + let attacker = attacker(); + start_cheat_caller_address(counter.contract_address, attacker); + + counter.increase_count(5); // Should panic + } + #[test] + fn test_increase_count_by_zero() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + counter.increase_count(0); + assert_eq!(counter.get_count(), 0); + + counter.increase_count(5); + counter.increase_count(0); + + assert_eq!(counter.get_count(), 5,); + + } + + #[test] + #[should_panic] + + fn test_increase_count_overflow() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + + counter.increase_count(U128_MAX); + assert_eq!(counter.get_count(), U128_MAX); + + counter.increase_count(1); +} + + #[test] + fn test_decrease_count_by_owner() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + counter.increase_count(20); + counter.decrease_count(7); + assert!(counter.get_count() == 13, "Count should be 13 after decrease"); + } + + + #[test] + fn test_decrease_count_to_zero() { + let owner = owner(); + let counter = deploy_contract(owner); + start_cheat_caller_address(counter.contract_address, owner); + counter.increase_count(5); + counter.decrease_count(5); + assert!(counter.get_count() == 0, "Count should reach exactly 0"); + } + + + #[test] + #[should_panic] + fn test_decrease_count_below_zero_panics() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + + counter.decrease_count(1); // count is 0, underflow expected + } + + + #[test] + #[should_panic(expected: "Only owner can change state")] + fn test_decrease_count_by_non_owner_panics() { + let owner = owner(); + let counter = deploy_contract(owner); + counter.increase_count(10); + + start_cheat_caller_address(counter.contract_address, attacker()); + counter.decrease_count(5); + } + + #[test] + fn test_decrease_count_by_zero() { + let owner = owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + counter.increase_count(10); + assert_eq!(counter.get_count(), 10); + + counter.decrease_count(0); + + assert_eq!(counter.get_count(), 10,); + + } + + #[test] + fn test_reset_count() { + let owner = contract_address_const::<'owner'>(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + + counter.reset_count(); + assert_eq!(counter.get_count(), 0); + + counter.increase_count(42); + assert_eq!(counter.get_count(), 42); + + counter.reset_count(); + assert_eq!(counter.get_count(), 0); + + counter.reset_count(); + assert_eq!(counter.get_count(), 0); + } + + + #[test] + #[should_panic(expected: "Only owner can change state")] + fn test_reset_count_not_owner() { + let owner = contract_address_const::<'owner'>(); + let counter = deploy_contract(owner); + + let attacker = attacker(); + start_cheat_caller_address(counter.contract_address, attacker); + + counter.reset_count(); + } + + #[test] + fn test_transfer_ownership() { + let owner = owner(); + let new_owner = new_owner(); + let counter = deploy_contract(owner); + + start_cheat_caller_address(counter.contract_address, owner); + + counter.transfer_ownership(new_owner); + assert_eq!(counter.get_owner(), new_owner); + + // New owner should now have access + start_cheat_caller_address(counter.contract_address, new_owner); + counter.increase_count(5); + assert_eq!(counter.get_count(), 5); + } + + #[test] + #[should_panic(expected: "Only owner can transfer")] + fn test_transfer_ownership_not_owner() { + let owner = owner(); + let counter = deploy_contract(owner); + + let attacker = attacker(); + start_cheat_caller_address(counter.contract_address, attacker); + + counter.transfer_ownership(attacker); // Should panic + } + + }