From 0ad395aa604b6151366c0a7b79db7df4a1d23bff Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Mon, 30 Sep 2024 10:22:38 +0100 Subject: [PATCH 1/4] feat: add the subtraction, multiplication and division functions --- assignments/assignment_3.md | 2 ++ src/lib.cairo | 63 +++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/assignments/assignment_3.md b/assignments/assignment_3.md index 2343306..7479aa8 100644 --- a/assignments/assignment_3.md +++ b/assignments/assignment_3.md @@ -5,3 +5,5 @@ - division 2. Complete [Starklings](https://starklings.app/) + + diff --git a/src/lib.cairo b/src/lib.cairo index 587aad4..579736f 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,24 +1,47 @@ fn main() { let sum_1: u8 = intro_to_uint(); let sum_2: u8 = sum_u8(2, 2); - + + let res_sub = sub(8, 5); + let res_div = div(10, 5); + let res_mult = mult(10, 2); + println!("result_1___ result_2: {} {} ", sum_1, sum_2); - } - - - fn intro_to_felt() -> felt252 { - let my_first_char: felt252 = 'GM'; - my_first_char - } - - fn intro_to_uint() -> u8 { - let x: u8 = 10; - let y: u8 = 20; - x + y - } - - fn sum_u8(x: u8, y: u8) -> u8 { - x + y - } - - \ No newline at end of file + + + println!("The subtraction result is {}", res_sub); + println!("The division result is {}", res_div); + println!("The multiplication result is {}", res_mult); +} + + +fn intro_to_felt() -> felt252 { + let my_first_char: felt252 = 'GM'; + my_first_char +} + +fn intro_to_uint() -> u8 { + let x: u8 = 10; + let y: u8 = 20; + x + y +} + +fn sum_u8(x: u8, y: u8) -> u8 { + x + y +} + +// / * - +fn sub(x: u8, y: u8) -> u8 { + x - y +} + +fn div(x: i8, y: i8) -> i8 { + x / y +} + +fn mult(x: u8, y: u8) -> u8 { + x * y +} + + +// https://starklings.app/gostean \ No newline at end of file From 55db5682184efeaeed4cbae1a2adf5e2e3678d4a Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Sat, 5 Oct 2024 11:46:35 +0100 Subject: [PATCH 2/4] ohh --- Scarb.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Scarb.toml b/Scarb.toml index d60f88b..8da58f3 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -6,11 +6,14 @@ edition = "2024_07" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -starknet = "2.8.2" +starknet = "2.8.0" +assert_macros = "2.8.0" [dev-dependencies] snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" } + [[target.starknet-contract]] +# name = "CounterV2" sierra = true From 4fedbb4771a432910370fb90e574f0a8400a1a4a Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Tue, 15 Oct 2024 17:52:08 +0100 Subject: [PATCH 3/4] feat(StudentRegistry) add test --- Scarb.toml | 13 +- src/errors.cairo | 4 + src/lib.cairo | 23 --- src/student_registry.cairo | 9 +- tests/test_student_registry.cairo | 264 +++++++++++++++++++++++++++++- 5 files changed, 278 insertions(+), 35 deletions(-) diff --git a/Scarb.toml b/Scarb.toml index b8fea0e..105632e 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -6,21 +6,14 @@ edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -<<<<<<< HEAD -starknet = "2.8.0" -assert_macros = "2.8.0" -======= -starknet = "^2.8.4" ->>>>>>> refs/remotes/origin/main +starknet = "^2.8.0" [dev-dependencies] snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.31.0" } -assert_macros = "2.8.4" - +assert_macros = "2.8.0" [[target.starknet-contract]] -# name = "CounterV2" sierra = true [scripts] -test = "snforge test" +test = "snforge test" \ No newline at end of file diff --git a/src/errors.cairo b/src/errors.cairo index 94f2680..0eda72a 100644 --- a/src/errors.cairo +++ b/src/errors.cairo @@ -5,4 +5,8 @@ pub mod Errors { pub const SAME_ADDRESS: felt252 = 'CANNOT BE SAME ADDRESS!'; pub const ZERO_VALUE: felt252 = 'CANNOT BE ZERO_VALUE!'; pub const STUDENT_NOT_REGISTERED: felt252 = 'STUDENT NOT REGISTERED!'; + pub const AGE_ZERO: felt252 = 'AGE CANNOT BE ZERO!'; + pub const ADMIN_CANNOT_BE_STUDENT: felt252 = 'ADMIN CANNOT BE STUDENT'; + pub const STUDENT_ALREADY_REGISTERED: felt252 = 'STUDENT ALREADY REGISTERED'; + } diff --git a/src/lib.cairo b/src/lib.cairo index 0fb685e..8140130 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -5,28 +5,5 @@ pub mod student_struct; pub mod errors; pub mod accounts; -<<<<<<< HEAD -mod sum; -mod subtraction; -mod division; -mod multiplication; - -fn main() { - let sum_2: u8 = sum::sum_u8(2, 2); - - let res_sub = subtraction::sub(8, 5); - let res_div = division::div(10, 5); - let res_mult = multiplication::mult(10, 2); - - - println!("result_2: {} ", sum_2); - - - println!("The subtraction result is {}", res_sub); - println!("The division result is {}", res_div); - println!("The multiplication result is {}", res_mult); -} -======= pub mod ownable_counter; pub mod addition; ->>>>>>> refs/remotes/origin/main diff --git a/src/student_registry.cairo b/src/student_registry.cairo index 10b0422..fb5e829 100644 --- a/src/student_registry.cairo +++ b/src/student_registry.cairo @@ -60,7 +60,14 @@ pub mod StudentRegistry { ) -> bool { // validation to check if student account is valid address and not a 0 address assert(!self.is_zero_address(_account), Errors::ZERO_ADDRESS); - assert(_age > 0, 'age cannot be 0'); + assert(_age > 0, Errors::AGE_ZERO); + // validation to check that the admin is not registering as a student + let current_admin = self.admin.read(); + assert(_account != current_admin, Errors::ADMIN_CANNOT_BE_STUDENT); + + // check if the student is already registered + let existing_student: Student = self.students_map.entry(_account).read(); + assert(existing_student.age == 0, Errors::STUDENT_ALREADY_REGISTERED); let student = Student { name: _name, account: _account, age: _age, xp: _xp, is_active: _is_active }; diff --git a/tests/test_student_registry.cairo b/tests/test_student_registry.cairo index 6bbd26c..c83ad85 100644 --- a/tests/test_student_registry.cairo +++ b/tests/test_student_registry.cairo @@ -1 +1,263 @@ -// Write test for the StudentRegistry contract here +// // Write test for the StudentRegistry contract here +use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; +use starknet::{ContractAddress}; +use cairo_bootcamp_3::student_registry::{IStudentRegistryDispatcher, IStudentRegistryDispatcherTrait}; + +pub mod Accounts { + use starknet::ContractAddress; + use core::traits::TryInto; + + pub fn zero() -> ContractAddress { + 0x0000000000000000000000000000000000000000.try_into().unwrap() + } + + pub fn admin() -> ContractAddress { + 'admin'.try_into().unwrap() + } + + pub fn student1() -> ContractAddress { + 'student1'.try_into().unwrap() + } + + pub fn student2() -> ContractAddress { + 'student2'.try_into().unwrap() + } + +} + +fn deploy(name: ByteArray) -> ContractAddress { + let contract = declare(name).unwrap().contract_class(); + let constructor_args = array![Accounts::admin().into()]; + let (contract_address, _) = contract.deploy(@constructor_args).unwrap(); + contract_address +} + +#[test] +fn test_can_add_student_correctly() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 12, + 30, + true, + ); + assert(result0 == true, 'Student added successfully'); +} + +#[test] +#[should_panic(expected: ('ZERO ADDRESS!',))] +fn test_address_can_not_be_zerro() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::zero(), + 12, + 30, + true, + ); + assert(result0 == false, 'Student address is zero'); +} + +#[test] +#[should_panic(expected: ('ADMIN CANNOT BE STUDENT',))] +fn test_cannot_add_admin() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::admin(), + 12, + 30, + true, + ); + assert(result0 == false, 'Admin cannot be student'); +} + +#[test] +#[should_panic(expected: ('STUDENT ALREADY REGISTERED',))] +fn test_cannot_add_registered_student() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 12, + 30, + true, + ); + assert(result0 == true, 'Student added successfully'); + + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 12, + 30, + true, + ); + assert(result0 == false, 'STUDENT ALREADY REGISTERED'); +} + +#[test] +#[should_panic(expected: ('AGE CANNOT BE ZERO!',))] +fn test_age_can_not_be_zero() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 0, + 30, + true, + ); + assert(result0 == false, 'Student added unsuccessfully'); +} + +#[test] +fn test_can_get_student() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 12, + 30, + true, + ); + + assert(result0 == true, 'Student added successfully'); + + let (name, account, age, xp, is_active) = contract_dispatcher.get_student(Accounts::student1()); + + assert(name == 'Alice', 'Name should match'); + assert(account == Accounts::student1(), 'Account should match'); + assert(age == 12, 'Age should match'); + assert(xp == 30, 'XP should match'); + assert(is_active == true, 'Is active should match'); +} + +#[test] +#[should_panic(expected: ('ZERO ADDRESS!',))] +fn test_can_not_get_address_zerro() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + contract_dispatcher.get_student(Accounts::zero()); +} + +#[test] +fn test_can_delete_student() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let result0 = contract_dispatcher.add_student( + 'Alice', + Accounts::student1(), + 12, + 30, + true, + ); + assert(result0 == true, 'Student added successfully'); + + let res = contract_dispatcher.delete_student(Accounts::student1()); + assert(res == true, 'Student deleted successfully'); + + let (name, account, age, xp, is_active) = contract_dispatcher.get_student(Accounts::student1()); + + // Check if the student is effectively deleted + assert(name == '', 'Name should be empty'); + assert(account == Accounts::zero(), 'Account should be zero address'); + assert(age == 0, 'Age should be 0'); + assert(xp == 0, 'XP should be 0'); + assert(!is_active, 'Is active should be false'); +} + +#[test] +fn test_update_student() { + + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let account1 = Accounts::student1(); + + let result0 = contract_dispatcher.add_student( + 'Alice', + account1, + 12, + 30, + true, + ); + assert(result0 == true, 'Student added successfully'); + + let result1 = contract_dispatcher.update_student( + 'Bob', + Accounts::student1(), + 14, + 25, + false, + ); + + assert(result1 == true, 'Student updated successfully'); + + let (name, account, age, xp, is_active) = contract_dispatcher.get_student(Accounts::student1()); + + // Check if the student is effectively deleted + assert(name == 'Bob', 'Name should be empty'); + assert(account == Accounts::student1(), 'Account should be zero address'); + assert(age == 14, 'Age should be 0'); + assert(xp == 25, 'XP should be 0'); + assert(is_active == false, 'Is active should be false'); +} + +#[test] +#[should_panic(expected: ('ZERO ADDRESS!',))] +fn test_can_not_update_address_zero() { + let contract_address = deploy("StudentRegistry"); + + let contract_dispatcher = IStudentRegistryDispatcher { contract_address }; + + let account1 = Accounts::student1(); + + let result0 = contract_dispatcher.add_student( + 'Alice', + account1, + 12, + 30, + true, + ); + assert(result0 == true, 'Student added successfully'); + + let result1 = contract_dispatcher.update_student( + 'Bob', + Accounts::zero(), + 14, + 25, + true, + ); + + assert(result1 == false, 'Student updated unsuccessfully'); +} + + + From 118aa0fe850f10809e5925e99298f5877a75b903 Mon Sep 17 00:00:00 2001 From: Stephanie Nwankwo Date: Wed, 16 Oct 2024 11:42:59 +0100 Subject: [PATCH 4/4] feat: ownable test --- tests/test_ownable.cairo | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/test_ownable.cairo diff --git a/tests/test_ownable.cairo b/tests/test_ownable.cairo new file mode 100644 index 0000000..e69de29