Skip to content
This repository was archived by the owner on Aug 8, 2024. It is now read-only.

Converted Ex02 and Ex03 to Cairo 2 #64

Open
wants to merge 2 commits into
base: cairo2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 71 additions & 40 deletions src/ex02.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
////////////////////////////////


#[contract]
#[starknet::contract]
mod Ex02 {

////////////////////////////////
// Core Library imports
// These are syscalls and functionalities that allow you to write Starknet contracts
Expand All @@ -38,69 +39,99 @@ mod Ex02 {
// In Cairo 1, storage is declared in a struct
// Storage is not visible by default through the ABI
////////////////////////////////
#[storage]
struct Storage {
// This variable is a u128, an unsigned integer (only positive values) stored over 128 bits
// You can use any of the following types: u8, u16, u32, u64, u128, bool, felt252, ContractAddress
// You can also use arrays of any of these types.
// For example: Array::<ContractAddress> for an array of addresses or Array::<u8> for an array of 8 bytes
// You can read and write to storage variables using the ::write() and ::read() functions, for example: my_secret_value_storage::write(42)
// To access state variables, you need to reference the contract state
// If you intend to modify state, you will need to use `ref self: ContractState` which is a mutable reference to the contract state
// But if you do not intend to modify state, you can use `self: @ContractState` which is a snapshot of the contract state
// You can read and write to storage variables using the `.write()` and `.read()` functions, for example: self.my_secret_value_storage.write(42)
my_secret_value_storage: u128,
}

////////////////////////////////
// View Functions
// Public variables should be declared explicitly with a getter function (indicated with #[view]) to be visible through the ABI and callable from other contracts
////////////////////////////////
#[view]
fn my_secret_value() -> u128 {
// The contract read the value with ::read()
// You may have noticed that in Cairo 1 all lines end with a semicolon.
// But this one doesn't. Why?
// Because, in this case, the return value is the result of the function call. The semicolon is not needed.
my_secret_value_storage::read()
}

////////////////////////////////
// Constructor
// This function (indicated with #[constructor]) is called when the contract is deployed and is used to initialize the contract's state
////////////////////////////////
#[constructor]
fn constructor(
ref self: ContractState,
_tderc20_address: ContractAddress,
_players_registry: ContractAddress,
_workshop_id: u128,
_exercise_id: u128,
my_secret_value: u128,
) {
ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id);
my_secret_value_storage::write(my_secret_value);
// The constructor takes a mutable reference to the contract state to enable it modify the state and instantiate state variables
self.ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id);
self.my_secret_value_storage.write(my_secret_value);
}



//////////////////////////////////////
// Ex02 trait implementation of Ex02Trait
///////////////////////////////////////

////////////////////////////////
// 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(my_value: u128) {
// Reading caller address using the Starknet core library function get_caller_address() (similar to msg.sender in Solidity)
// and storing it in a variable called sender_address.
let sender_address = get_caller_address();
// Reading the secret value from storage using the read function from the storage variable my_secret_value_storage
let my_secret_value = my_secret_value_storage::read();
// Checking that the value sent is the same as the secret value stored in storage using the assert function
// Using assert this way is similar to using "require" in Solidity
assert(my_value == my_secret_value, 'Wrong secret value');
// Checking if the user has validated the exercise before sending points using the validate_exercise function from the Ex00Base contract
validate_exercise(sender_address);
// Sending points to the address specified as parameter using the distribute_points function from the Ex00Base contract
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) {
update_class_hash_by_admin(class_hash);
// The functions in the Ex02TraitImpl block are callable by other contracts or external calls and are indicated with #[external(v0)] to make them availiable in the ABI
// The generate_trait attribute is used to automatically generate a trait for the impl block
///////////////////////////////////

#[external(v0)]
#[generate_trait]
impl Ex02TraitImpl of Ex02Trait{

////////////////////////////////
// View Functions
// Public variables should be declared explicitly with a getter function to be visible through the ABI and callable from other contracts
// By taking a snapshot of the ContractState, we ensure that this function can not modify the Contract State and hence can be seen as a view function
////////////////////////////////
fn my_secret_value(self: @ContractState) -> u128 {
// The contract read the value with .read()
// You may have noticed that in Cairo 1 all lines end with a semicolon.
// But this one doesn't. Why?
// Because, in this case, the return value is the result of the function call. The semicolon is not needed.
// Since self is a snapshot of the contract state, it cannot be modified.
self.my_secret_value_storage.read()
}


////////////////////////////////
// Mutable functions
// These functions are callable by other contracts or external calls such as DAPP,
// By taking a reference to the ContractState, this function can modify the Contract State (this is similar to an external or public function in solidity )
////////////////////////////////
fn claim_points(ref self: ContractState, my_value: u128) {
// Reading caller address using the Starknet core library function get_caller_address() (similar to msg.sender in Solidity)
// and storing it in a variable called sender_address.
let sender_address = get_caller_address();
// Reading the secret value from storage using the read function from the storage variable my_secret_value_storage
let my_secret_value = self.my_secret_value_storage.read();
// Checking that the value sent is the same as the secret value stored in storage using the assert function
// Using assert this way is similar to using "require" in Solidity
assert(my_value == my_secret_value, 'Wrong secret value');
// Checking if the user has validated the exercise before sending points using the validate_exercise function from the Ex00Base contract
self.validate_exercise(sender_address);
// Sending points to the address specified as parameter using the distribute_points function from the Ex00Base contract
self.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.
////////////////////////////////
fn update_class_hash(ref self: ContractState, class_hash: felt252) {
self.update_class_hash_by_admin(class_hash);
}

}


}
147 changes: 84 additions & 63 deletions src/ex03.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
// - How to throw an error using the Cairo assert function
////////////////////////////////

#[contract]


#[starknet::contract]
mod Ex03 {

////////////////////////////////
// Core Library imports
// These are syscalls and functionalities that allow you to write Starknet contracts
Expand All @@ -39,12 +42,13 @@ mod Ex03 {
// In Cairo 1, storage is declared in a struct
// Storage is not visible by default through the ABI
////////////////////////////////
#[storage]
struct Storage {
// This variable is a LegacyMap. It is equivalent to a mapping in Solidity.
// It is used to store a counter (of type u128) for each user address (of type ContractAddress) in the contract's storage
// The user_counters variable is private and can only be accessed through the getter function declared below
// To read the u128 value from a LegacyMap, use the read function (e.g. user_counters::read(sender_address))
// To write a u128 value to a LegacyMap (mapping a u128 to a ContractAddress), use the write function (e.g. user_counters::write(sender_address, 0_u128))
// To read the u128 value from a LegacyMap, use the read function (e.g. self.user_counters.read(sender_address))
// To write a u128 value to a LegacyMap (mapping a u128 to a ContractAddress), use the write function (e.g. self.user_counters.write(sender_address, 0_u128))
user_counters: LegacyMap::<ContractAddress, u128>,
}

Expand All @@ -54,81 +58,98 @@ mod Ex03 {
////////////////////////////////
#[constructor]
fn constructor(
_tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128
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);
self.ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id);
}

////////////////////////////////
// View Functions
// Public variables should be declared explicitly with a getter function (indicated with #[view]) to be visible through the ABI and callable from other contracts
////////////////////////////////
#[view]
fn get_user_counters(account: ContractAddress) -> u128 {
// We are not calling the read function without any parameter (e.g. user_counters::read()) but with a parameter (e.g. user_counters::read(sender_address))
// because we want to read the value of the mapping for a specific key (the sender address)
let user_counter = user_counters::read(account);
// We return the value of the counter. We can return a value without using the return keyword, similar to Rust
user_counter
}


///////////////////////////////////////
// Ex03 trait implementation of Ex03 trait
///////////////////////////////////////

////////////////////////////////
// External functions
// These functions are callable by other contracts or external calls and are indicated with #[external] (similar to "public" in Solidity)
// The functions in the Ex03TraitImpl block are callable by other contracts or external calls and are indicated with #[external(v0)] to make them availiable in the ABI
// The generate_trait attribute is used to automatically generate a trait for the impl block
////////////////////////////////
// You can alter the state of the contract by calling external functions such as increment_counter, decrement_counter and reset_counter
// After you altered the state of the contract, you can read from the contract's storage using the get_user_counters function to check if the counter is equal to 3
// Then you can call the claim_points function to check if the counter is equal to 3 and if so credit the user with points
#[external]
fn increment_counter() {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reading the counter from storage for the sender address (the key of the mapping) and storing it in a variable
let current_counter_value = user_counters::read(sender_address);
// Writing updated value to storage (incrementing the counter by 2)
user_counters::write(sender_address, current_counter_value + 2_u128);
}
//////////////////////////////////

#[external]
fn decrement_counter() {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reading counter from storage
let current_counter_value = user_counters::read(sender_address);
// Writing updated value to storage (decrementing the counter by 1)
user_counters::write(sender_address, current_counter_value - 1_u128);
}
#[external(v0)]
#[generate_trait]
impl Ex03TraitImpl of Ex03Trait {
////////////////////////////////
// View Functions
// By taking a snapshot of the ContractState, we ensure that this function can not modify the Contract State and hence can be seen as a view function
////////////////////////////////
fn get_user_counters(self: @ContractState, account: ContractAddress) -> u128 {
// We are not calling the read function without any parameter (e.g. self.user_counters.read()) but with a parameter (e.g. self.user_counters.read(sender_address))
// because we want to read the value of the mapping for a specific key (the sender address)
let user_counter = self.user_counters.read(account);
// We return the value of the counter. We can return a value without using the return keyword, similar to Rust
user_counter
}

#[external]
fn reset_counter() {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reinitializing the user counter to 0 (resetting it)
user_counters::write(sender_address, 0_u128);
}

////////////////////////////////
// Mutable Functions
// By taking a reference to the ContractState, this function can modify the Contract State (this is similar to an external or public function in solidity )
////////////////////////////////
fn increment_counter(ref self: ContractState) {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reading the counter from storage for the sender address (the key of the mapping) and storing it in a variable
let current_counter_value = self.user_counters.read(sender_address);
// Writing updated value to storage (incrementing the counter by 2)
self.user_counters.write(sender_address, current_counter_value + 2_u128);
}

#[external]
fn claim_points() {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Checking that user's counter is equal to 3 (the value we want to reach) and throwing an error if it is not
let current_counter_value = user_counters::read(sender_address);
// We are using the Cairo assert function to throw an error if the condition is not met
assert(current_counter_value == 3_u128, 'Counter is not equal to 3');

// 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) {
update_class_hash_by_admin(class_hash);
fn decrement_counter(ref self: ContractState) {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reading counter from storage
let current_counter_value = self.user_counters.read(sender_address);
// Writing updated value to storage (decrementing the counter by 1)
self.user_counters.write(sender_address, current_counter_value - 1_u128);
}


fn reset_counter(ref self: ContractState) {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Reinitializing the user counter to 0 (resetting it)
self.user_counters.write(sender_address, 0_u128);
}



fn claim_points(ref self: ContractState) {
// Reading caller address
let sender_address: ContractAddress = get_caller_address();
// Checking that user's counter is equal to 3 (the value we want to reach) and throwing an error if it is not
let current_counter_value = self.user_counters.read(sender_address);
// We are using the Cairo assert function to throw an error if the condition is not met
assert(current_counter_value == 3_u128, 'Counter is not equal to 3');

// Checking if the user has validated the exercise before
self.validate_exercise(sender_address);
// Sending points to the address specified as parameter
self.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.
////////////////////////////////
fn update_class_hash(ref self: ContractState, class_hash: felt252) {
self.update_class_hash_by_admin(class_hash);
}
}


}