From d8638e9a8abba77b12aca785b0f318c755fbcc3c Mon Sep 17 00:00:00 2001 From: Carlos Colorado Date: Sun, 9 Jul 2023 01:31:56 -0600 Subject: [PATCH 1/2] Migrate ex01 to Cairo2 --- src/ex01.cairo | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/ex01.cairo b/src/ex01.cairo index ea660d4..13fc812 100644 --- a/src/ex01.cairo +++ b/src/ex01.cairo @@ -9,8 +9,14 @@ // - General smart contract syntax and structure //////////////////////////////// +#[starknet::interface] +trait Ex01Trait { + fn claim_points(ref self:T); + fn update_class_hash(ref self:T, class_hash: felt252); +} + // Contracts are defined using the #[contract] attribute (similar to "contract" in Solidity) and are defined in a module -#[contract] +#[starknet::contract] mod Ex01 { //////////////////////////////// // Core Library imports @@ -28,6 +34,10 @@ mod Ex01 { use starknet_cairo_101::utils::ex00_base::Ex00Base::distribute_points; use starknet_cairo_101::utils::ex00_base::Ex00Base::update_class_hash_by_admin; + #[storage] + struct Storage { + } + //////////////////////////////// // Constructor // This function (indicated with #[constructor]) is called once, when the contract is deployed, and is used to initialize the contract's state @@ -36,7 +46,7 @@ mod Ex01 { // When you deploy the contract, you need to pass these parameters to the constructor function // For these exercises you do not need to worry about the parameters, they are automatically passed to the constructor. #[constructor] - fn constructor(_tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128) { + fn constructor(ref self: ContractState, _tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128) { ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id); } @@ -44,22 +54,24 @@ mod Ex01 { // External functions // These functions are callable by other contracts or external calls such as DAPP, which are indicated with #[external] (similar to "public" in Solidity) //////////////////////////////// - #[external] - fn claim_points() { + #[external(v0)] + impl Ex01Impl of super::Ex01Trait { + fn claim_points(ref self: ContractState) { // Reading caller address let sender_address = get_caller_address(); // Checking if the user has validated the exercise before validate_exercise(sender_address); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); - } - //////////////////////////////// - // External functions - Administration - // Only admins can call these. You don't need to understand them to finish the exercise. - //////////////////////////////// - #[external] - fn update_class_hash(class_hash: felt252) { + } + + //////////////////////////////// + // External functions - Administration + // Only admins can call these. You don't need to understand them to finish the exercise. + //////////////////////////////// + fn update_class_hash(ref self: ContractState, class_hash: felt252) { update_class_hash_by_admin(class_hash); + } } } From 2c928eb0851f12e47f8f9e51ffb3b58b0960b0f8 Mon Sep 17 00:00:00 2001 From: Carlos Colorado Date: Wed, 12 Jul 2023 19:26:26 -0600 Subject: [PATCH 2/2] WIP figuring out how to import `use` internal for contracts internal functions ```cairo error: Identifier not found. --> ex01.cairo:32:57 use starknet_cairo_101::utils::ex00_base::Ex00Base::validate_exercise; ^***************^ error: Identifier not found. --> ex01.cairo:33:57 use starknet_cairo_101::utils::ex00_base::Ex00Base::ex_initializer; ^************^ error: Identifier not found. --> ex01.cairo:34:57 use starknet_cairo_101::utils::ex00_base::Ex00Base::distribute_points; ^***************^ error: Identifier not found. --> ex01.cairo:35:57 use starknet_cairo_101::utils::ex00_base::Ex00Base::update_class_hash_by_admin; ``` ^************************^ --- src/utils/ex00_base.cairo | 134 ++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/src/utils/ex00_base.cairo b/src/utils/ex00_base.cairo index a0e6596..463a169 100644 --- a/src/utils/ex00_base.cairo +++ b/src/utils/ex00_base.cairo @@ -4,14 +4,32 @@ // such as `validate_exercise`, `distribute_points` //////////////////////////////// +use starknet::ContractAddress; -#[contract] +#[starknet::interface] +trait Ex00BaseTrait { + fn has_validated_exercise(ref self:T, account: ContractAddress) -> bool ; + fn ex_initializer(ref self:T); + + fn tderc20_address(self: @T) -> ContractAddress ; + fn players_registry(self: @T) -> ContractAddress ; + fn workshop_id(self: @T) -> u128 ; + fn exercise_id(self: @T) -> u128 ; + + // fn validate_exercise(ref self:T, account: ContractAddress) ; + // fn distribute_points(ref self: ContractState, to: ContractAddress, amount: u128) { + // fn update_class_hash_by_admin(ref self:T, class_hash_in_felt: felt252) ; + + +} + +#[Starknet::contract] mod Ex00Base { // Core Library Imports use starknet::get_caller_address; use zeroable::Zeroable; use starknet::ContractAddress; - use starknet::ContractAddressZeroable; + // use starknet::ContractAddressZeroable; use starknet::syscalls::replace_class_syscall; use starknet::ClassHash; use starknet::class_hash::Felt252TryIntoClassHash; @@ -33,6 +51,7 @@ mod Ex00Base { //////////////////////////////// // STORAGE //////////////////////////////// + #[storage] struct Storage { tderc20_address_storage: ContractAddress, players_registry_storage: ContractAddress, @@ -40,88 +59,89 @@ mod Ex00Base { exercise_id_storage: u128, } - //////////////////////////////// - // View Functions - //////////////////////////////// - #[view] - fn tderc20_address() -> ContractAddress { - tderc20_address_storage::read() - } + #[external(v0)] + impl Ex00BaseImpl of super::Ex00BaseTrait { + //////////////////////////////// + // View Functions + //////////////////////////////// + fn tderc20_address(self: @ContractState) -> ContractAddress { + self.tderc20_address_storage.read() + } - #[view] - fn players_registry() -> ContractAddress { - players_registry_storage::read() - } + fn players_registry(self: @ContractState) -> ContractAddress { + self.players_registry_storage.read() + } - #[view] - fn workshop_id() -> u128 { - workshop_id_storage::read() - } + fn workshop_id(self: @ContractState) -> u128 { + self.workshop_id_storage.read() + } - #[view] - fn exercise_id() -> u128 { - exercise_id_storage::read() - } + fn exercise_id(self: @ContractState) -> u128 { + self.exercise_id_storage.read() + } - #[view] - fn has_validated_exercise(account: ContractAddress) -> bool { + fn has_validated_exercise(self: @ContractState, account: ContractAddress) -> bool { // reading player registry - let players_registry = players_registry_storage::read(); - let workshop_id = workshop_id_storage::read(); - let exercise_id = exercise_id_storage::read(); + let players_registry = self.players_registry_storage.read(); + let workshop_id = self.workshop_id_storage.read(); + let exercise_id = self.exercise_id_storage.read(); Iplayers_registryDispatcher{contract_address: players_registry} - .has_validated_exercise(account, workshop_id, exercise_id) - } - - //////////////////////////////// - // Internal Constructor - //////////////////////////////// - fn ex_initializer( - _tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128 - ) { - tderc20_address_storage::write(_tderc20_address); - players_registry_storage::write(_players_registry); - workshop_id_storage::write(_workshop_id); - exercise_id_storage::write(_exercise_id); + .has_validated_exercise(account, workshop_id, exercise_id) + } + + //////////////////////////////// + // Internal Constructor + //////////////////////////////// + fn ex_initializer( + ref self: ContractState, _tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128 + ) { + self.tderc20_address_storage.write(_tderc20_address); + self.players_registry_storage.write(_players_registry); + self.workshop_id_storage.write(_workshop_id); + self.exercise_id_storage.write(_exercise_id); + } } - //////////////////////////////// - // Internal Functions - //////////////////////////////// - fn distribute_points(to: ContractAddress, amount: u128) { + #[generate_trait] + impl PrivateMethods of PrivateMethodsTrait { + //////////////////////////////// + // Internal Functions + //////////////////////////////// + fn distribute_points(ref self: ContractState, to: ContractAddress, amount: u128) { // Retrieving contract address from storage - let tderc20_address = tderc20_address_storage::read(); + let tderc20_address = self.tderc20_address_storage.read(); let points_to_credit: u128 = amount * Decimals; ITDERC20Dispatcher{contract_address: tderc20_address} - .distribute_points(to, points_to_credit); - } + .distribute_points(to, points_to_credit); + } - fn validate_exercise(account: ContractAddress) { + fn validate_exercise(self: @ContractState, account: ContractAddress) { // reading player registry - let players_registry = players_registry_storage::read(); - let workshop_id = workshop_id_storage::read(); - let exercise_id = exercise_id_storage::read(); + let players_registry = self.players_registry_storage.read(); + let workshop_id = self.workshop_id_storage.read(); + let exercise_id = self.exercise_id_storage.read(); let has_current_user_validated_exercise = - Iplayers_registryDispatcher{contract_address: players_registry} - .has_validated_exercise(account, workshop_id, exercise_id); + Iplayers_registryDispatcher{contract_address: players_registry} + .has_validated_exercise(account, workshop_id, exercise_id); assert(has_current_user_validated_exercise == false, 'Exercise previously validated'); Iplayers_registryDispatcher{contract_address: players_registry} - .validate_exercise(account, workshop_id, exercise_id); - } + .validate_exercise(account, workshop_id, exercise_id); + } - fn update_class_hash_by_admin(class_hash_in_felt: felt252) { - let players_registry = players_registry_storage::read(); + fn update_class_hash_by_admin(self: @ContractState, class_hash_in_felt: felt252) { + let players_registry = self.players_registry_storage.read(); let sender_address = get_caller_address(); let is_admin = Iplayers_registryDispatcher{contract_address: players_registry} - .is_exercise_or_admin(sender_address); + .is_exercise_or_admin(sender_address); assert (is_admin == true, 'CALLER_NO_ADMIN_RIGHTS'); let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); replace_class_syscall(class_hash); + } } }