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..12e2a8c --- /dev/null +++ b/yahia008/assignment_1/src/assignment1.cairo @@ -0,0 +1,74 @@ +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(0, 0); + match add_result { + Result::Ok(v) => { + assert!(v==0, "assertion failed") + println!("add value {}", v) + }, + Result::Err(_) => println!("add error ", ), + }; + + let mul_result = 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 = divide(10, 2); + match div_result { + 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) => { + assert!(v==3, "assertion failed") + 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; 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..f177898 --- /dev/null +++ b/yahia008/assignment_2/src/lib.cairo @@ -0,0 +1,77 @@ +mod 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::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..e716f0a --- /dev/null +++ b/yahia008/assignment_2/src/mylogic.cairo @@ -0,0 +1,24 @@ +use core::num::traits::CheckedAdd; +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') +} + +pub fn reset_count() -> u128 { + 0 +} \ No newline at end of file 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..b91c594 --- /dev/null +++ b/yahia008/av2_pro/arithmetic_logic/src/mylogic.cairo @@ -0,0 +1,46 @@ +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 { + if x == 0 || y == 0 { + return Result::Ok(0); + } + 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/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 new file mode 100644 index 0000000..22bde39 --- /dev/null +++ b/yahia008/av2_pro/counterv2_pro/src/lib.cairo @@ -0,0 +1,4 @@ +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 + } + + } 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;