From d1af9be8092221084dc3b5d481a9b110e1ca8ed8 Mon Sep 17 00:00:00 2001 From: msaug Date: Sat, 25 Nov 2023 22:47:31 +0100 Subject: [PATCH 1/3] refactor: replace externalv0 by abi(embed_v0) --- .../cairo_cheatsheet/src/array_example.cairo | 35 +++++++------ .../cairo_cheatsheet/src/felt_example.cairo | 28 ++++++---- .../cairo_cheatsheet/src/loop_example.cairo | 20 +++++--- .../src/mapping_example.cairo | 47 ++++++++++------- .../cairo_cheatsheet/src/match_example.cairo | 51 +++++++++++-------- .../cairo_cheatsheet/src/struct_example.cairo | 31 ++++++----- .../cairo_cheatsheet/src/tuple_example.cairo | 13 +++-- .../src/type_casting_example.cairo | 27 ++++++---- .../calling_other_contracts/src/callee.cairo | 10 ++-- .../calling_other_contracts/src/caller.cairo | 10 ++-- .../errors/src/custom_errors.cairo | 13 +++-- .../errors/src/simple_errors.cairo | 12 +++-- .../errors/src/vault_errors.cairo | 13 +++-- .../events/src/counter.cairo | 10 ++-- .../interfaces_traits/src/implicit.cairo | 21 -------- .../src/implicit_internal.cairo | 5 +- .../interfaces_traits/src/lib.cairo | 1 - .../mappings/src/mappings.cairo | 15 ++++-- .../variables/src/global_variables.cairo | 12 +++-- .../variables/src/local_variables.cairo | 11 ++-- .../variables/src/storage_variables.cairo | 14 ++--- .../constant_product_amm/src/contracts.cairo | 8 +-- .../ch01-applications/erc20/src/token.cairo | 2 +- scripts/cairo_programs_verifier.sh | 2 +- src/ch00/interacting/interfaces-traits.md | 10 ---- 25 files changed, 235 insertions(+), 186 deletions(-) delete mode 100644 listings/ch00-getting-started/interfaces_traits/src/implicit.cairo diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo index 616701a0..5169f017 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/array_example.cairo @@ -1,29 +1,32 @@ +#[starknet::interface] +trait IArrayExample { + fn createarray(self: @TContractState, num_one: u32, num_two: u32, num_three: u32) -> bool; +} + #[starknet::contract] -mod arrayExample { +mod ArrayExample { #[storage] struct Storage {} - #[external(v0)] - #[generate_trait] - impl external of externalTrait { - fn createArray(self: @ContractState, numOne: u32, numTwo: u32, numThree: u32) -> bool { - let mut Arr = ArrayTrait::::new(); - Arr.append(numOne); - Arr.append(numTwo); - Arr.append(numThree); + #[abi(embed_v0)] + impl External of super::IArrayExample { + fn createarray(self: @ContractState, num_one: u32, num_two: u32, num_three: u32) -> bool { + let mut arr = ArrayTrait::::new(); + arr.append(num_one); + arr.append(num_two); + arr.append(num_three); - let ArrLength: usize = Arr.len(); - assert(ArrLength == 3, 'Array Length should be 3'); + assert(arr.len() == 3, 'array length should be 3'); - let first_value = Arr.pop_front().unwrap(); - assert(first_value == numOne, 'Both values should match'); + let first_value = arr.pop_front().unwrap(); + assert(first_value == num_one, 'first value should match'); - let second_value = *Arr.at(0); - assert(second_value == numTwo, 'Both values should match too'); + let second_value = *arr.at(0); + assert(second_value == num_two, 'second value should match'); //Returns true if an array is empty, then false if it isn't. - Arr.is_empty() + arr.is_empty() } } } diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/felt_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/felt_example.cairo index 7425b0c2..0cde034b 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/felt_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/felt_example.cairo @@ -1,24 +1,30 @@ +use starknet::ContractAddress; +#[starknet::interface] +trait IFelt252Example { + fn store_name(ref self: TContractState, name: felt252) -> felt252; + fn view_name(self: @TContractState, address: ContractAddress) -> felt252; +} + #[starknet::contract] -mod feltExample { +mod Felt252Example { use starknet::{ContractAddress, get_caller_address}; #[storage] struct Storage { - userName: LegacyMap::, + user_name: LegacyMap::, } - #[external(v0)] - #[generate_trait] - impl external of externlalTrait { - fn storeName(ref self: ContractState, name: felt252) -> felt252 { - self.userName.write(get_caller_address(), name); + #[abi(embed_v0)] + impl External of super::IFelt252Example { + fn store_name(ref self: ContractState, name: felt252) -> felt252 { + self.user_name.write(get_caller_address(), name); - let welcomeMsg: felt252 = 'Welcome to StarknetByExample'; - welcomeMsg + let welcome_msg: felt252 = 'Welcome to StarknetByExample'; + welcome_msg } - fn viewName(self: @ContractState, Add: ContractAddress) -> felt252 { - self.userName.read(Add) + fn view_name(self: @ContractState, address: ContractAddress) -> felt252 { + self.user_name.read(address) } } } diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/loop_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/loop_example.cairo index 29af6bb1..d7551f8d 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/loop_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/loop_example.cairo @@ -1,25 +1,29 @@ +#[starknet::interface] +trait ILoopExample { + fn gather_evens(ref self: TContractState, maxLimit: u32) -> Array; +} + #[starknet::contract] -mod loopExample { +mod LoopExample { #[storage] struct Storage {} - #[external(v0)] - #[generate_trait] - impl external of externlalTrait { - fn gatherEvens(ref self: ContractState, maxLimit: u32) -> Array { + #[abi(embed_v0)] + impl External of super::ILoopExample { + fn gather_evens(ref self: ContractState, maxLimit: u32) -> Array { let mut i: u32 = 0; - let mut Arr = ArrayTrait::new(); + let mut arr = ArrayTrait::new(); loop { if i == maxLimit { break; }; if (i % 2 == 0) { - Arr.append(i); + arr.append(i); } i += 1; }; - return Arr; + return arr; } } } diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/mapping_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/mapping_example.cairo index a91fa66c..bd107b91 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/mapping_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/mapping_example.cairo @@ -1,37 +1,50 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait IMappingExample { + fn register_user(ref self: TContractState, student_add: ContractAddress, studentName: felt252); + fn record_student_score( + ref self: TContractState, student_add: ContractAddress, subject: felt252, score: u16 + ); + fn view_student_name(self: @TContractState, student_add: ContractAddress) -> felt252; + fn view_student_score( + self: @TContractState, student_add: ContractAddress, subject: felt252 + ) -> u16; +} + #[starknet::contract] -mod mappingContract { +mod MappingContract { use starknet::ContractAddress; #[storage] struct Storage { - studentsName: LegacyMap::, - studentsResultRecord: LegacyMap::<(ContractAddress, felt252), u16>, + students_name: LegacyMap::, + students_result_record: LegacyMap::<(ContractAddress, felt252), u16>, } - #[external(v0)] - #[generate_trait] - impl external of externalTrait { - fn registerUser( - ref self: ContractState, studentAdd: ContractAddress, studentName: felt252 + #[abi(embed_v0)] + impl External of super::IMappingExample { + fn register_user( + ref self: ContractState, student_add: ContractAddress, studentName: felt252 ) { - self.studentsName.write(studentAdd, studentName); + self.students_name.write(student_add, studentName); } - fn recordStudentScore( - ref self: ContractState, studentAdd: ContractAddress, Subject: felt252, score: u16 + fn record_student_score( + ref self: ContractState, student_add: ContractAddress, subject: felt252, score: u16 ) { - self.studentsResultRecord.write((studentAdd, Subject), score); + self.students_result_record.write((student_add, subject), score); } - fn viewStudentName(self: @ContractState, studentAdd: ContractAddress) -> felt252 { - self.studentsName.read(studentAdd) + fn view_student_name(self: @ContractState, student_add: ContractAddress) -> felt252 { + self.students_name.read(student_add) } - fn viewStudentScore( - self: @ContractState, studentAdd: ContractAddress, Subject: felt252 + fn view_student_score( + self: @ContractState, student_add: ContractAddress, subject: felt252 ) -> u16 { // for a 2D mapping its important to take note of the amount of brackets being used. - self.studentsResultRecord.read((studentAdd, Subject)) + self.students_result_record.read((student_add, subject)) } } } diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/match_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/match_example.cairo index 2095e152..c0f50c84 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/match_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/match_example.cairo @@ -1,28 +1,37 @@ +#[starknet::interface] +trait IMatchExample { + fn value_in_cents(self: @TContractState, coin: Coin) -> felt252; + fn specified_colour(self: @TContractState, colour: Colour) -> felt252; + fn quiz(self: @TContractState, num: felt252) -> felt252; +} + + +#[derive(Drop, Serde)] +enum Colour { + Red, + Blue, + Green, + Orange, + Black +} + +#[derive(Drop, Serde)] +enum Coin { + Penny, + Nickel, + Dime, + Quarter, +} + + #[starknet::contract] -mod matchExample { +mod MatchExample { + use super::{Colour, Coin}; #[storage] struct Storage {} - #[derive(Drop, Serde)] - enum Colour { - Red, - Blue, - Green, - Orange, - Black - } - - #[derive(Drop, Serde)] - enum Coin { - Penny, - Nickel, - Dime, - Quarter, - } - - #[external(v0)] - #[generate_trait] - impl external of externlalTrait { + #[abi(embed_v0)] + impl External of super::IMatchExample { fn value_in_cents(self: @ContractState, coin: Coin) -> felt252 { match coin { Coin::Penny => 1, diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/struct_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/struct_example.cairo index f5e0fbc8..eb3a1a42 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/struct_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/struct_example.cairo @@ -1,30 +1,37 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait IStructExample { + fn store_struct(ref self: TContractState, age: u8); + fn read_struct(self: @TContractState) -> (ContractAddress, u8); +} + #[starknet::contract] mod StructExample { use starknet::{ContractAddress, get_caller_address}; #[storage] struct Storage { - userData: data + user_data: Data } #[derive(Drop, starknet::Store)] - struct data { - Add: ContractAddress, - Age: u8 + struct Data { + address: ContractAddress, + age: u8 } - #[external(v0)] - #[generate_trait] - impl StoreStructImpl of IStoreStructContract { + #[abi(embed_v0)] + impl StoreStructImpl of super::IStructExample { fn store_struct(ref self: ContractState, age: u8) { - let newStruct = data { Add: get_caller_address(), Age: age }; - self.userData.write(newStruct); + let new_struct = Data { address: get_caller_address(), age: age }; + self.user_data.write(new_struct); } fn read_struct(self: @ContractState) -> (ContractAddress, u8) { - let lastUser = self.userData.read(); - let add = lastUser.Add; - let age = lastUser.Age; + let last_user = self.user_data.read(); + let add = last_user.address; + let age = last_user.age; (add, age) } } diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/tuple_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/tuple_example.cairo index b795c1b9..672c3dc9 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/tuple_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/tuple_example.cairo @@ -1,3 +1,11 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait ITupleExample { + fn store_tuple(self: @TContractState, address: ContractAddress, age: u64, active: bool); + fn read_tuple(self: @TContractState) -> (ContractAddress, u64, bool); +} + #[starknet::contract] mod TupleExample { use starknet::{ContractAddress, get_caller_address}; @@ -7,9 +15,8 @@ mod TupleExample { user_data: (ContractAddress, u64, bool) } - #[external(v0)] - #[generate_trait] - impl TupleExampleImpl of ITupleExampleImpl { + #[abi(embed_v0)] + impl TupleExampleImpl of super::ITupleExample { fn store_tuple(ref self: ContractState, address: ContractAddress, age: u64, active: bool) { let user_tuple = (address, age, active); self.user_data.write(user_tuple); diff --git a/listings/ch00-getting-started/cairo_cheatsheet/src/type_casting_example.cairo b/listings/ch00-getting-started/cairo_cheatsheet/src/type_casting_example.cairo index e855b614..85043be5 100644 --- a/listings/ch00-getting-started/cairo_cheatsheet/src/type_casting_example.cairo +++ b/listings/ch00-getting-started/cairo_cheatsheet/src/type_casting_example.cairo @@ -1,27 +1,32 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait ITypecastingExample { + fn type_casting(self: @TContractState, rand_number: u32); +} #[starknet::contract] -mod typecasting_Example { +mod TypecastingExample { #[storage] struct Storage {} - #[external(v0)] - #[generate_trait] - impl external of externlalTrait { - fn typeCasting(self: @ContractState, randNumber: u32) { + #[abi(embed_v0)] + impl External of super::ITypecastingExample { + fn type_casting(self: @ContractState, rand_number: u32) { let my_felt252 = 15; // Since a u32 might not fit in a u8 and a u16, we need to use try_into, // then unwrap the Option type thats returned. - let new_u8: u8 = randNumber.try_into().unwrap(); - let new_u16: u16 = randNumber.try_into().unwrap(); + let new_u8: u8 = rand_number.try_into().unwrap(); + let new_u16: u16 = rand_number.try_into().unwrap(); - // since new_u32 is the of the same type (u32) as randNumber, we can directly assign them, + // since new_u32 is the of the same type (u32) as rand_number, we can directly assign them, // or use the .into() method. - let new_u32: u32 = randNumber; + let new_u32: u32 = rand_number; // When typecasting from a smaller size to an equal or larger size we use the .into() method. // Note: u64 and u128 are larger than u32, so a u32 type will always fit into them. - let new_u64: u64 = randNumber.into(); - let new_u128: u128 = randNumber.into(); + let new_u64: u64 = rand_number.into(); + let new_u128: u128 = rand_number.into(); // Since a felt252 is smaller than a u256, we can use the into() method let new_u256: u256 = my_felt252.into(); diff --git a/listings/ch00-getting-started/calling_other_contracts/src/callee.cairo b/listings/ch00-getting-started/calling_other_contracts/src/callee.cairo index a9191534..af21b716 100644 --- a/listings/ch00-getting-started/calling_other_contracts/src/callee.cairo +++ b/listings/ch00-getting-started/calling_other_contracts/src/callee.cairo @@ -1,3 +1,8 @@ +#[starknet::interface] +trait ICallee { + fn set_value(ref self: TContractState, value: u128) -> u128; +} + #[starknet::contract] mod Callee { #[storage] @@ -5,9 +10,8 @@ mod Callee { value: u128, } - #[abi(per_item)] - #[generate_trait] - impl ICalleeImpl of ICallee { + #[abi(embed_v0)] + impl ICalleeImpl of super::ICallee { fn set_value(ref self: ContractState, value: u128) -> u128 { self.value.write(value); value diff --git a/listings/ch00-getting-started/calling_other_contracts/src/caller.cairo b/listings/ch00-getting-started/calling_other_contracts/src/caller.cairo index d3368be3..56603292 100644 --- a/listings/ch00-getting-started/calling_other_contracts/src/caller.cairo +++ b/listings/ch00-getting-started/calling_other_contracts/src/caller.cairo @@ -7,6 +7,11 @@ trait ICallee { fn set_value(ref self: TContractState, value: u128) -> u128; } +#[starknet::interface] +trait ICaller { + fn set_value_from_address(ref self: TContractState, addr: ContractAddress, value: u128); +} + #[starknet::contract] mod Caller { // We import the Dispatcher of the called contract @@ -16,9 +21,8 @@ mod Caller { #[storage] struct Storage {} - #[abi(per_item)] - #[generate_trait] - impl ICallerImpl of ICaller { + #[abi(embed_v0)] + impl ICallerImpl of super::ICaller { fn set_value_from_address(ref self: ContractState, addr: ContractAddress, value: u128) { ICalleeDispatcher { contract_address: addr }.set_value(value); } diff --git a/listings/ch00-getting-started/errors/src/custom_errors.cairo b/listings/ch00-getting-started/errors/src/custom_errors.cairo index 014ac206..ccbc386d 100644 --- a/listings/ch00-getting-started/errors/src/custom_errors.cairo +++ b/listings/ch00-getting-started/errors/src/custom_errors.cairo @@ -3,6 +3,12 @@ mod Errors { const NOT_NULL: felt252 = 'must not be null'; } +#[starknet::interface] +trait ICustomErrorsExample { + fn test_assert(self: @TContractState, i: u256); + fn test_panic(self: @TContractState, i: u256); +} + #[starknet::contract] mod CustomErrorsExample { use super::Errors; @@ -10,15 +16,12 @@ mod CustomErrorsExample { #[storage] struct Storage {} - #[abi(per_item)] - #[generate_trait] - impl CustomErrorsExample of ICustomErrorsExample { - #[external(v0)] + #[abi(embed_v0)] + impl CustomErrorsExample of super::ICustomErrorsExample { fn test_assert(self: @ContractState, i: u256) { assert(i > 0, Errors::NOT_POSITIVE); } - #[external(v0)] fn test_panic(self: @ContractState, i: u256) { if (i == 0) { panic_with_felt252(Errors::NOT_NULL); diff --git a/listings/ch00-getting-started/errors/src/simple_errors.cairo b/listings/ch00-getting-started/errors/src/simple_errors.cairo index 0251f1b7..f7af9558 100644 --- a/listings/ch00-getting-started/errors/src/simple_errors.cairo +++ b/listings/ch00-getting-started/errors/src/simple_errors.cairo @@ -1,19 +1,21 @@ +#[starknet::interface] +trait IErrorsExample { + fn test_assert(self: @TContractState, i: u256); + fn test_panic(self: @TContractState, i: u256); +} #[starknet::contract] mod ErrorsExample { #[storage] struct Storage {} - #[abi(per_item)] - #[generate_trait] - impl ErrorsExample of IErrorsExample { - #[external(v0)] + #[abi(embed_v0)] + impl ErrorsExample of super::IErrorsExample { fn test_assert(self: @ContractState, i: u256) { // Assert used to validate a condition // and abort execution if the condition is not met assert(i > 0, 'i must be greater than 0'); } - #[external(v0)] fn test_panic(self: @ContractState, i: u256) { if (i == 0) { // Panic used to abort execution directly diff --git a/listings/ch00-getting-started/errors/src/vault_errors.cairo b/listings/ch00-getting-started/errors/src/vault_errors.cairo index dc27e521..0f72a4db 100644 --- a/listings/ch00-getting-started/errors/src/vault_errors.cairo +++ b/listings/ch00-getting-started/errors/src/vault_errors.cairo @@ -3,6 +3,12 @@ mod VaultErrors { // you can define more errors here } +#[starknet::interface] +trait IVaultErrorsExample { + fn deposit(ref self: TContractState, amount: u256); + fn withdraw(ref self: TContractState, amount: u256); +} + #[starknet::contract] mod VaultErrorsExample { use super::VaultErrors; @@ -12,17 +18,14 @@ mod VaultErrorsExample { balance: u256, } - #[abi(per_item)] - #[generate_trait] - impl VaultErrorsExample of IVaultErrorsExample { - #[external(v0)] + #[abi(embed_v0)] + impl VaultErrorsExample of super::IVaultErrorsExample { fn deposit(ref self: ContractState, amount: u256) { let mut balance = self.balance.read(); balance = balance + amount; self.balance.write(balance); } - #[external(v0)] fn withdraw(ref self: ContractState, amount: u256) { let mut balance = self.balance.read(); diff --git a/listings/ch00-getting-started/events/src/counter.cairo b/listings/ch00-getting-started/events/src/counter.cairo index ca3fdfdd..473a7024 100644 --- a/listings/ch00-getting-started/events/src/counter.cairo +++ b/listings/ch00-getting-started/events/src/counter.cairo @@ -1,3 +1,7 @@ +#[starknet::interface] +trait IEventCounter { + fn increment(ref self: TContractState); +} #[starknet::contract] mod EventCounter { use starknet::{get_caller_address, ContractAddress}; @@ -31,10 +35,8 @@ mod EventCounter { new_value: u128, } - #[abi(per_item)] - #[generate_trait] - impl EventCounter of IEventCounter { - #[external(v0)] + #[abi(embed_v0)] + impl EventCounter of super::IEventCounter { fn increment(ref self: ContractState) { let mut counter = self.counter.read(); counter += 1; diff --git a/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo b/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo deleted file mode 100644 index 3b98cc62..00000000 --- a/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo +++ /dev/null @@ -1,21 +0,0 @@ -#[starknet::contract] -mod ImplicitInterfaceContract { - #[storage] - struct Storage { - value: u32 - } - - #[abi(per_item)] - #[generate_trait] - impl ImplicitInterfaceContract of IImplicitInterfaceContract { - #[external(v0)] - fn get_value(self: @ContractState) -> u32 { - self.value.read() - } - - #[external(v0)] - fn set_value(ref self: ContractState, value: u32) { - self.value.write(value); - } - } -} diff --git a/listings/ch00-getting-started/interfaces_traits/src/implicit_internal.cairo b/listings/ch00-getting-started/interfaces_traits/src/implicit_internal.cairo index baf6dfe8..c6b79eec 100644 --- a/listings/ch00-getting-started/interfaces_traits/src/implicit_internal.cairo +++ b/listings/ch00-getting-started/interfaces_traits/src/implicit_internal.cairo @@ -7,8 +7,6 @@ trait IImplicitInternalContract { #[starknet::contract] mod ImplicitInternalContract { - use super::IImplicitInternalContract; - #[storage] struct Storage { value: u32 @@ -16,7 +14,6 @@ mod ImplicitInternalContract { #[generate_trait] impl InternalFunctions of InternalFunctionsTrait { - #[external(v0)] fn set_value(ref self: ContractState, value: u32) { self.value.write(value); } @@ -31,7 +28,7 @@ mod ImplicitInternalContract { } #[abi(embed_v0)] - impl ImplicitInternalContract of IImplicitInternalContract { + impl ImplicitInternalContract of super::IImplicitInternalContract { fn add(ref self: ContractState, nb: u32) { self.set_value(self.value.read() + nb); } diff --git a/listings/ch00-getting-started/interfaces_traits/src/lib.cairo b/listings/ch00-getting-started/interfaces_traits/src/lib.cairo index 5ec40a24..0d308659 100644 --- a/listings/ch00-getting-started/interfaces_traits/src/lib.cairo +++ b/listings/ch00-getting-started/interfaces_traits/src/lib.cairo @@ -1,5 +1,4 @@ mod explicit; -mod implicit; mod implicit_internal; #[cfg(test)] diff --git a/listings/ch00-getting-started/mappings/src/mappings.cairo b/listings/ch00-getting-started/mappings/src/mappings.cairo index ea885f83..dcf9e537 100644 --- a/listings/ch00-getting-started/mappings/src/mappings.cairo +++ b/listings/ch00-getting-started/mappings/src/mappings.cairo @@ -1,3 +1,11 @@ +use starknet::ContractAddress; + +#[starknet::interface] +trait IMapContract { + fn set(ref self: TContractState, key: ContractAddress, value: felt252); + fn get(self: @TContractState, key: ContractAddress) -> felt252; +} + #[starknet::contract] mod MapContract { use starknet::ContractAddress; @@ -8,15 +16,12 @@ mod MapContract { map: LegacyMap::, } - #[abi(per_item)] - #[generate_trait] - impl MapContractImpl of IMapContract { - #[external(v0)] + #[abi(embed_v0)] + impl MapContractImpl of super::IMapContract { fn set(ref self: ContractState, key: ContractAddress, value: felt252) { self.map.write(key, value); } - #[external(v0)] fn get(self: @ContractState, key: ContractAddress) -> felt252 { self.map.read(key) } diff --git a/listings/ch00-getting-started/variables/src/global_variables.cairo b/listings/ch00-getting-started/variables/src/global_variables.cairo index 8a77f404..c60b0163 100644 --- a/listings/ch00-getting-started/variables/src/global_variables.cairo +++ b/listings/ch00-getting-started/variables/src/global_variables.cairo @@ -1,15 +1,17 @@ +#[starknet::interface] +trait IGlobalExample { + fn foo(ref self: TContractState); +} #[starknet::contract] mod GlobalExample { - // import the required functions from the starknet core library + // import the required functions from the starknet core library use starknet::get_caller_address; #[storage] struct Storage {} - #[abi(per_item)] - #[generate_trait] - impl GlobalExampleImpl of IGlobalExample { - #[external(v0)] + #[abi(embed_v0)] + impl GlobalExampleImpl of super::IGlobalExample { fn foo(ref self: ContractState) { // Call the get_caller_address function to get the sender address let caller = get_caller_address(); diff --git a/listings/ch00-getting-started/variables/src/local_variables.cairo b/listings/ch00-getting-started/variables/src/local_variables.cairo index 5bd38657..3ccaf1b4 100644 --- a/listings/ch00-getting-started/variables/src/local_variables.cairo +++ b/listings/ch00-getting-started/variables/src/local_variables.cairo @@ -1,12 +1,15 @@ +#[starknet::interface] +trait ILocalVariablesExample { + fn do_something(self: @TContractState, value: u32) -> u32; +} + #[starknet::contract] mod LocalVariablesExample { #[storage] struct Storage {} - #[abi(per_item)] - #[generate_trait] - impl LocalVariablesExample of ILocalVariablesExample { - #[external(v0)] + #[abi(embed_v0)] + impl LocalVariablesExample of super::ILocalVariablesExample { fn do_something(self: @ContractState, value: u32) -> u32 { // This variable is local to the current block. It can't be accessed once it goes out of scope. let increment = 10; diff --git a/listings/ch00-getting-started/variables/src/storage_variables.cairo b/listings/ch00-getting-started/variables/src/storage_variables.cairo index 1fd81af2..6bd105ae 100644 --- a/listings/ch00-getting-started/variables/src/storage_variables.cairo +++ b/listings/ch00-getting-started/variables/src/storage_variables.cairo @@ -1,3 +1,8 @@ +#[starknet::interface] +trait IStorageVariableExample { + fn set(ref self: TContractState, value: u32); + fn get(self: @TContractState) -> u32; +} #[starknet::contract] mod StorageVariablesExample { // All storage variables are contained in a struct called Storage @@ -8,18 +13,15 @@ mod StorageVariablesExample { value: u32 } - #[abi(per_item)] - #[generate_trait] - impl StorageVariablesExample of IStorageVariableExample { + #[abi(embed_v0)] + impl StorageVariablesExample of super::IStorageVariableExample { // Write to storage variables by sending a transaction that calls an external function - #[external(v0)] fn set(ref self: ContractState, value: u32) { self.value.write(value); } // Read from storage variables without sending transactions - #[external(v0)] - fn get(ref self: ContractState) -> u32 { + fn get(self: @ContractState) -> u32 { self.value.read() } } diff --git a/listings/ch01-applications/constant_product_amm/src/contracts.cairo b/listings/ch01-applications/constant_product_amm/src/contracts.cairo index 5bc4843b..b68e529a 100644 --- a/listings/ch01-applications/constant_product_amm/src/contracts.cairo +++ b/listings/ch01-applications/constant_product_amm/src/contracts.cairo @@ -77,7 +77,7 @@ mod ConstantProductAmm { } } - #[external(v0)] + #[abi(embed_v0)] impl ConstantProductAmm of super::IConstantProductAmm { fn swap(ref self: ContractState, token_in: ContractAddress, amount_in: u256) -> u256 { assert(amount_in > 0, 'amount in = 0'); @@ -162,7 +162,7 @@ mod ConstantProductAmm { // // L1 * T = L0 * (T + s) // - // (L1 - L0) * T / L0 = s + // (L1 - L0) * T / L0 = s // Claim // (L1 - L0) / L0 = dx / x = dy / y @@ -183,7 +183,7 @@ mod ConstantProductAmm { // // --- Equation 3 --- // Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / (sqrt(x^2) - // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2) + // = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2) // = ((x + dx) - x) / x // = dx / x // Since dx / dy = x / y, @@ -233,7 +233,7 @@ mod ConstantProductAmm { // v = s / T * L // sqrt(dxdy) = s / T * sqrt(xy) // - // Amount of liquidity to remove must not change price so + // Amount of liquidity to remove must not change price so // dx / dy = x / y // // replace dy = dx * y / x diff --git a/listings/ch01-applications/erc20/src/token.cairo b/listings/ch01-applications/erc20/src/token.cairo index eb04fcfb..836ec5f2 100644 --- a/listings/ch01-applications/erc20/src/token.cairo +++ b/listings/ch01-applications/erc20/src/token.cairo @@ -87,7 +87,7 @@ mod erc20 { self.mint(recipient, initial_supply); } - #[external(v0)] + #[abi(embed_v0)] impl IERC20Impl of super::IERC20 { fn get_name(self: @ContractState) -> felt252 { self.name.read() diff --git a/scripts/cairo_programs_verifier.sh b/scripts/cairo_programs_verifier.sh index 529d20d1..318c3235 100755 --- a/scripts/cairo_programs_verifier.sh +++ b/scripts/cairo_programs_verifier.sh @@ -15,7 +15,7 @@ git_setup() { else git remote add upstream "$desired_url" echo "'upstream' remote added to NethermindEth." - fi + fi git fetch upstream } diff --git a/src/ch00/interacting/interfaces-traits.md b/src/ch00/interacting/interfaces-traits.md index c9922fac..3e6dd47f 100644 --- a/src/ch00/interacting/interfaces-traits.md +++ b/src/ch00/interacting/interfaces-traits.md @@ -21,16 +21,6 @@ In summary, there's two ways to handle interfaces: Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit.cairo). -## Implicit interface - -```rust -{{#include ../../../listings/ch00-getting-started/interfaces_traits/src/implicit.cairo}} -``` - -Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo). - -> Note: You can import an implicitly generated contract interface with `use contract::{GeneratedContractInterface}`. However, the `Dispatcher` will not be generated automatically. - ## Internal functions You can also use `#[generate_trait]` for your internal functions. From 7f3d36f0b540f42ad1d3c37785b76c38ac774e40 Mon Sep 17 00:00:00 2001 From: msaug Date: Sat, 25 Nov 2023 22:51:42 +0100 Subject: [PATCH 2/3] refactor: remove implicit interfaces --- src/ch00/interacting/interfaces-traits.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ch00/interacting/interfaces-traits.md b/src/ch00/interacting/interfaces-traits.md index 3e6dd47f..39f6794f 100644 --- a/src/ch00/interacting/interfaces-traits.md +++ b/src/ch00/interacting/interfaces-traits.md @@ -6,12 +6,9 @@ In cairo, to specify the interface you need to define a trait annotated with `#[ When a function needs to access the contract state, it must have a `self` parameter of type `ContractState`. This implies that the corresponding function signature in the interface trait must also take a `TContractState` type as a parameter. It's important to note that every function in the contract interface must have this `self` parameter of type `TContractState`. -You can use the `#[generate_trait]` attribute to implicitly generate the trait for a specific implementation block. This attribute automatically generates a trait with the same functions as the ones in the implemented block, replacing the `self` parameter with a generic `TContractState` parameter. +You can use the `#[generate_trait]` attribute to implicitly generate the trait for a specific implementation block. This attribute automatically generates a trait with the same functions as the ones in the implemented block, replacing the `self` parameter with a generic `TContractState` parameter. However, this will only work for internal functions, and not for functions that are part of the contract's public interface - as embedding an impl inside the abi of a contract requires this impl to implement an interface. -In summary, there's two ways to handle interfaces: - -- Explicitly, by defining a trait annoted with `#[starknet::interface]` -- Implicitly, by using the `#[generate_trait]` attribute +In summary, there's only one way to handle interfaces, which is explicitly, by defining a trait annoted with `#[starknet::interface]`. You cannot define an interface implicitly, by annotating an `#[abi(embed_v0)]` impl inside a contract with `#[generate_trait]`. ## Explicit interface From 28a03f082ad686084fd8742588c6fd803d0451f8 Mon Sep 17 00:00:00 2001 From: msaug Date: Sun, 26 Nov 2023 10:07:48 +0100 Subject: [PATCH 3/3] fix: restore implicit interface abi_per_item based --- .../interfaces_traits/src/implicit.cairo | 21 +++++++++++++++++++ .../interfaces_traits/src/lib.cairo | 1 + src/ch00/interacting/interfaces-traits.md | 17 +++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 listings/ch00-getting-started/interfaces_traits/src/implicit.cairo diff --git a/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo b/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo new file mode 100644 index 00000000..3b98cc62 --- /dev/null +++ b/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo @@ -0,0 +1,21 @@ +#[starknet::contract] +mod ImplicitInterfaceContract { + #[storage] + struct Storage { + value: u32 + } + + #[abi(per_item)] + #[generate_trait] + impl ImplicitInterfaceContract of IImplicitInterfaceContract { + #[external(v0)] + fn get_value(self: @ContractState) -> u32 { + self.value.read() + } + + #[external(v0)] + fn set_value(ref self: ContractState, value: u32) { + self.value.write(value); + } + } +} diff --git a/listings/ch00-getting-started/interfaces_traits/src/lib.cairo b/listings/ch00-getting-started/interfaces_traits/src/lib.cairo index 0d308659..73b9608f 100644 --- a/listings/ch00-getting-started/interfaces_traits/src/lib.cairo +++ b/listings/ch00-getting-started/interfaces_traits/src/lib.cairo @@ -1,5 +1,6 @@ mod explicit; mod implicit_internal; +mod implicit; #[cfg(test)] mod tests; diff --git a/src/ch00/interacting/interfaces-traits.md b/src/ch00/interacting/interfaces-traits.md index 39f6794f..6318a7b2 100644 --- a/src/ch00/interacting/interfaces-traits.md +++ b/src/ch00/interacting/interfaces-traits.md @@ -6,9 +6,12 @@ In cairo, to specify the interface you need to define a trait annotated with `#[ When a function needs to access the contract state, it must have a `self` parameter of type `ContractState`. This implies that the corresponding function signature in the interface trait must also take a `TContractState` type as a parameter. It's important to note that every function in the contract interface must have this `self` parameter of type `TContractState`. -You can use the `#[generate_trait]` attribute to implicitly generate the trait for a specific implementation block. This attribute automatically generates a trait with the same functions as the ones in the implemented block, replacing the `self` parameter with a generic `TContractState` parameter. However, this will only work for internal functions, and not for functions that are part of the contract's public interface - as embedding an impl inside the abi of a contract requires this impl to implement an interface. +You can use the `#[generate_trait]` attribute to implicitly generate the trait for a specific implementation block. This attribute automatically generates a trait with the same functions as the ones in the implemented block, replacing the `self` parameter with a generic `TContractState` parameter. However, you will need to annotate the block with the `#[abi(per_item)]` attribute, and each function with the appropriate attribute depending on whether it's an external function, a constructor or a l1 handler. -In summary, there's only one way to handle interfaces, which is explicitly, by defining a trait annoted with `#[starknet::interface]`. You cannot define an interface implicitly, by annotating an `#[abi(embed_v0)]` impl inside a contract with `#[generate_trait]`. +In summary, there's two ways to handle interfaces: + +- Explicitly, by defining a trait annoted with `#[starknet::interface]` +- Implicitly, by using `#[generate_trait]` combined with the #[abi(per_item)]` attributes, and annotating each function inside the implementation block with the appropriate attribute. ## Explicit interface @@ -18,6 +21,16 @@ In summary, there's only one way to handle interfaces, which is explicitly, by d Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/interfaces_traits/src/explicit.cairo). +## Implicit interface + +```rust +{{#include ../../../listings/ch00-getting-started/interfaces_traits/src/implicit.cairo}} +``` + +Play with this contract in [Remix](https://remix.ethereum.org/?#activate=Starknet&url=https://github.com/NethermindEth/StarknetByExample/blob/main/listings/ch00-getting-started/interfaces_traits/src/implicit.cairo). + +> Note: You can import an implicitly generated contract interface with `use contract::{GeneratedContractInterface}`. However, the `Dispatcher` will not be generated automatically. + ## Internal functions You can also use `#[generate_trait]` for your internal functions.