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

Migratetocairo2 #66

Draft
wants to merge 2 commits into
base: cairo2
Choose a base branch
from
Draft
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
34 changes: 23 additions & 11 deletions src/ex01.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
// - General smart contract syntax and structure
////////////////////////////////

#[starknet::interface]
trait Ex01Trait<T> {
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
Expand All @@ -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
Expand All @@ -36,30 +46,32 @@ 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);
}

////////////////////////////////
// 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<ContractState> {
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);
}
}

}
134 changes: 77 additions & 57 deletions src/utils/ex00_base.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@
// such as `validate_exercise`, `distribute_points`
////////////////////////////////

use starknet::ContractAddress;

#[contract]
#[starknet::interface]
trait Ex00BaseTrait<T> {
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;
Copy link

@TosinJs TosinJs Jul 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using this (starknet::contract_address::ContractAddressZeroable) in place of the comment.

https://book.cairo-lang.org/appendix-05-most-common-types-and-traits.html#:~:text=starknet%3A%3Acontract_address%3A%3AContractAddressZeroable

use starknet::syscalls::replace_class_syscall;
use starknet::ClassHash;
use starknet::class_hash::Felt252TryIntoClassHash;
Expand All @@ -33,95 +51,97 @@ mod Ex00Base {
////////////////////////////////
// STORAGE
////////////////////////////////
#[storage]
struct Storage {
tderc20_address_storage: ContractAddress,
players_registry_storage: ContractAddress,
workshop_id_storage: u128,
exercise_id_storage: u128,
}

////////////////////////////////
// View Functions
////////////////////////////////
#[view]
fn tderc20_address() -> ContractAddress {
tderc20_address_storage::read()
}
#[external(v0)]
impl Ex00BaseImpl of super::Ex00BaseTrait<ContractState> {
////////////////////////////////
// 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);
}
}
}