diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index edc55ce..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "snyk.advanced.autoSelectOrganization": true -} \ No newline at end of file diff --git a/starknet_contracts/.gitignore b/CairoTest-1/starknet_contracts/.gitignore similarity index 100% rename from starknet_contracts/.gitignore rename to CairoTest-1/starknet_contracts/.gitignore diff --git a/starknet_contracts/Scarb.lock b/CairoTest-1/starknet_contracts/Scarb.lock similarity index 88% rename from starknet_contracts/Scarb.lock rename to CairoTest-1/starknet_contracts/Scarb.lock index 6c8c64a..6975e6c 100644 --- a/starknet_contracts/Scarb.lock +++ b/CairoTest-1/starknet_contracts/Scarb.lock @@ -1,6 +1,10 @@ # Code generated by scarb DO NOT EDIT. version = 1 +[[package]] +name = "cairo_program" +version = "0.1.0" + [[package]] name = "snforge_scarb_plugin" version = "0.56.0" @@ -20,5 +24,6 @@ dependencies = [ name = "starknet_contracts" version = "0.1.0" dependencies = [ + "cairo_program", "snforge_std", ] diff --git a/starknet_contracts/Scarb.toml b/CairoTest-1/starknet_contracts/Scarb.toml similarity index 98% rename from starknet_contracts/Scarb.toml rename to CairoTest-1/starknet_contracts/Scarb.toml index 29cf20f..d915936 100644 --- a/starknet_contracts/Scarb.toml +++ b/CairoTest-1/starknet_contracts/Scarb.toml @@ -7,6 +7,7 @@ edition = "2024_07" [dependencies] starknet = "2.18.0" +cairo_program = { path = "../cairo_program" } [dev-dependencies] snforge_std = "0.56.0" diff --git a/starknet_contracts/snfoundry.toml b/CairoTest-1/starknet_contracts/snfoundry.toml similarity index 100% rename from starknet_contracts/snfoundry.toml rename to CairoTest-1/starknet_contracts/snfoundry.toml diff --git a/CairoTest-1/starknet_contracts/src/lib.cairo b/CairoTest-1/starknet_contracts/src/lib.cairo new file mode 100644 index 0000000..342d044 --- /dev/null +++ b/CairoTest-1/starknet_contracts/src/lib.cairo @@ -0,0 +1,79 @@ +/// Interface representing `HelloContract`. +/// This interface allows modification and retrieval of the contract's storage count. +#[starknet::interface] +pub trait ICounter { + /// Increase count. + fn increase_count(ref self: T, amount: u32); + /// Decrease count. + fn reduce_count(ref self: T, amount: u32); + /// Multiply count. + fn multiply_count(ref self: T, amount: u32); + /// Divide count. + fn divide_count(ref self: T, amount: u32); + /// Retrieve count. + fn get_count(self: @T) -> u32; +} + +/// Simple contract for managing count. +#[starknet::contract] +mod Counter { + use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; + use starknet::{ContractAddress, get_caller_address}; + use cairo_program::integer::{add_num, sub_num, mul_num, div_num}; + + #[storage] + struct Storage { + count: u32, + owner: ContractAddress, + } + + #[constructor] + fn constructor(ref self: ContractState, owner: ContractAddress) { + self.owner.write(owner); + } + + #[generate_trait] + impl InternalImpl of InternalTrait { + fn only_owner(self: @ContractState) { + assert(get_caller_address() == self.owner.read(), 'Caller is not the owner'); + } + } + + #[abi(embed_v0)] + impl CounterImpl of super::ICounter { + fn increase_count(ref self: ContractState, amount: u32) { + self.only_owner(); + assert(amount != 0, 'Amount cannot be 0'); + let current = self.count.read(); + let new_count = add_num(current, amount); + self.count.write(new_count); + } + + fn reduce_count(ref self: ContractState, amount: u32) { + self.only_owner(); + let current = self.count.read(); + let new_count = sub_num(current, amount); + self.count.write(new_count); + } + + fn multiply_count(ref self: ContractState, amount: u32) { + self.only_owner(); + assert(amount != 0, 'Amount cannot be 0'); + let current = self.count.read(); + let new_count = mul_num(current, amount); + self.count.write(new_count); + } + + fn divide_count(ref self: ContractState, amount: u32) { + self.only_owner(); + assert(amount != 0, 'Amount cannot be 0'); + let current = self.count.read(); + let new_count = div_num(current, amount); + self.count.write(new_count); + } + + fn get_count(self: @ContractState) -> u32 { + self.count.read() + } + } +} diff --git a/CairoTest-1/starknet_contracts/src/restricted_token.cairo b/CairoTest-1/starknet_contracts/src/restricted_token.cairo new file mode 100644 index 0000000..2424de6 --- /dev/null +++ b/CairoTest-1/starknet_contracts/src/restricted_token.cairo @@ -0,0 +1,249 @@ +use starknet::ContractAddress; + +#[starknet::interface] +pub trait IERC20 { + fn get_name(self: @TContractState) -> felt252; + fn get_symbol(self: @TContractState) -> felt252; + fn get_decimals(self: @TContractState) -> u8; + fn get_total_supply(self: @TContractState) -> u256; + fn balance_of(self: @TContractState, account: ContractAddress) -> u256; + fn allowance( + self: @TContractState, owner: ContractAddress, spender: ContractAddress, + ) -> u256; + fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256); + fn transfer_from( + ref self: TContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256, + ); + fn approve(ref self: TContractState, spender: ContractAddress, amount: u256); + fn increase_allowance(ref self: TContractState, spender: ContractAddress, added_value: u256); + fn decrease_allowance( + ref self: TContractState, spender: ContractAddress, subtracted_value: u256, + ); + fn burn(ref self: TContractState, amount: u256); + fn revoke(ref self: TContractState, account: ContractAddress); + fn update_transfer_limit(ref self: TContractState, new_limit: u256); + fn get_transfer_limit(self: @TContractState) -> u256; + fn mint(ref self: TContractState, recipient: ContractAddress, amount: u256); +} +#[starknet::contract] +pub mod erc20 { + + use core::num::traits::Zero; + use starknet::get_caller_address; + use starknet::ContractAddress; + use starknet::storage::{ Map, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess,StoragePointerWriteAccess,}; + + #[storage] + struct Storage { + name: felt252, + symbol: felt252, + decimals: u8, + total_supply: u256, + balances: Map::, + allowances: Map::<(ContractAddress, ContractAddress), u256>, + admin: ContractAddress, + transfer_limit: u256, + revoked: Map::, + } + + #[event] + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub enum Event { + Transfer: Transfer, + Approval: Approval, + Burn: Burn, + Revoke: Revoke, + LimitUpdated: LimitUpdated, + } + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub struct Transfer { + pub from: ContractAddress, + pub to: ContractAddress, + pub value: u256, + } + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub struct Approval { + pub owner: ContractAddress, + pub spender: ContractAddress, + pub value: u256, + } + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub struct Burn { + pub from: ContractAddress, + pub value: u256, + } + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub struct Revoke { + pub account: ContractAddress, + } + #[derive(Copy, Drop, Debug, PartialEq, starknet::Event)] + pub struct LimitUpdated { + pub new_limit: u256, + } + + mod Errors { + pub const APPROVE_FROM_ZERO: felt252 = 'ERC20: approve from 0'; + pub const APPROVE_TO_ZERO: felt252 = 'ERC20: approve to 0'; + pub const TRANSFER_FROM_ZERO: felt252 = 'ERC20: transfer from 0'; + pub const TRANSFER_TO_ZERO: felt252 = 'ERC20: transfer to 0'; + pub const BURN_FROM_ZERO: felt252 = 'ERC20: burn from 0'; + pub const MINT_TO_ZERO: felt252 = 'ERC20: mint to 0'; + pub const TRANSFER_LIMIT_EXCEEDED: felt252 = 'ERC20: transfer limit exceeded'; + pub const ACCOUNT_REVOKED: felt252 = 'ERC20: account revoked'; + pub const UNAUTHORIZED: felt252 = 'ERC20: unauthorized'; + } + + #[constructor] + fn constructor( + ref self: ContractState, + owner:ContractAddress, + recipient: ContractAddress, + name: felt252, + decimals: u8, + initial_supply: u256, + symbol: felt252, + ) { + self.name.write(name); + self.symbol.write(symbol); + self.decimals.write(decimals); + self.admin.write(owner); + self.transfer_limit.write(10000_u256); + self.mint(recipient, initial_supply); + } + + #[abi(embed_v0)] + impl IERC20Impl of super::IERC20 { + fn get_name(self: @ContractState) -> felt252 { + self.name.read() + } + + fn get_symbol(self: @ContractState) -> felt252 { + self.symbol.read() + } + + fn get_decimals(self: @ContractState) -> u8 { + self.decimals.read() + } + + fn get_total_supply(self: @ContractState) -> u256 { + self.total_supply.read() + } + + fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { + self.balances.read(account) + } + + fn allowance(self: @ContractState, owner: ContractAddress, spender: ContractAddress,) -> u256 { + self.allowances.read((owner, spender)) + } + + fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) { + let sender = get_caller_address(); + self._transfer(sender, recipient, amount); + } + + fn transfer_from(ref self: ContractState,sender: ContractAddress,recipient: ContractAddress,amount: u256,) { + let caller = get_caller_address(); + self.spend_allowance(sender, caller, amount); + self._transfer(sender, recipient, amount); + } + + fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) { + let caller = get_caller_address(); + self.approve_helper(caller, spender, amount); + } + + fn increase_allowance(ref self: ContractState, spender: ContractAddress, added_value: u256) { + let caller = get_caller_address(); + self.approve_helper(caller, spender, self.allowances.read((caller, spender)) + added_value,); + } + + fn decrease_allowance(ref self: ContractState, spender: ContractAddress, subtracted_value: u256,) { + let caller = get_caller_address(); + self.approve_helper(caller, spender, self.allowances.read((caller, spender)) - subtracted_value); + } + + fn burn(ref self: ContractState, amount: u256) { + let caller = get_caller_address(); + assert(caller == self.admin.read(), Errors::UNAUTHORIZED); + assert(amount.is_non_zero(), Errors::BURN_FROM_ZERO); + self.balances.write(caller, self.balances.read(caller) - amount); + self.total_supply.write(self.total_supply.read() - amount); + self.balances.write(Zero::zero(), self.balances.read(Zero::zero()) + amount); + self.emit(Event::Burn(Burn { from: caller, value: amount })); + } + + fn revoke(ref self: ContractState, account: ContractAddress) { + assert(get_caller_address() == self.admin.read(), Errors::UNAUTHORIZED); + self.revoked.write(account, true); + self.emit(Event::Revoke(Revoke { account })); + } + + fn update_transfer_limit(ref self: ContractState, new_limit: u256) { + assert(get_caller_address() == self.admin.read(), Errors::UNAUTHORIZED); + self.transfer_limit.write(new_limit); + self.emit(Event::LimitUpdated(LimitUpdated { new_limit })); + } + + fn get_transfer_limit(self: @ContractState) -> u256 { + self.transfer_limit.read() + } + + fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) { + assert(get_caller_address() == self.admin.read(), Errors::UNAUTHORIZED); + self._mint(recipient, amount); + } + } + + #[generate_trait] + impl InternalImpl of InternalTrait { + fn _transfer( + ref self: ContractState, + sender: ContractAddress, + recipient: ContractAddress, + amount: u256, + ) { + assert(sender.is_non_zero(), Errors::TRANSFER_FROM_ZERO); + assert(recipient.is_non_zero(), Errors::TRANSFER_TO_ZERO); + assert(!self.revoked.read(sender), Errors::ACCOUNT_REVOKED); + let limit = self.transfer_limit.read(); + assert(amount <= limit, Errors::TRANSFER_LIMIT_EXCEEDED); + self.balances.write(sender, self.balances.read(sender) - amount); + self.balances.write(recipient, self.balances.read(recipient) + amount); + self.emit(Transfer { from: sender, to: recipient, value: amount }); + } + + fn spend_allowance( + ref self: ContractState, + owner: ContractAddress, + spender: ContractAddress, + amount: u256, + ) { + let allowance = self.allowances.read((owner, spender)); + self.allowances.write((owner, spender), allowance - amount); + } + + fn approve_helper( + ref self: ContractState, + owner: ContractAddress, + spender: ContractAddress, + amount: u256, + ) { + assert(spender.is_non_zero(), Errors::APPROVE_TO_ZERO); + self.allowances.write((owner, spender), amount); + self.emit(Approval { owner, spender, value: amount }); + } + + fn _mint(ref self: ContractState, recipient: ContractAddress, amount: u256) { + assert(recipient.is_non_zero(), Errors::MINT_TO_ZERO); + let supply = self.total_supply.read() + amount; + self.total_supply.write(supply); + let balance = self.balances.read(recipient) + amount; + self.balances.write(recipient, balance); + self.emit(Event::Transfer(Transfer {from: Zero::zero(), to: recipient, value: amount},),); + } + } +} \ No newline at end of file diff --git a/CairoTest-2/Readme.md b/CairoTest-2/Readme.md new file mode 100644 index 0000000..a086d91 --- /dev/null +++ b/CairoTest-2/Readme.md @@ -0,0 +1 @@ +This is the link to my TEST-2 on the Starknetagentic: https://github.com/chukwudiikeh/Starknet- \ No newline at end of file diff --git a/cairo_program/.gitignore b/cairo_program/.gitignore deleted file mode 100644 index eb5a316..0000000 --- a/cairo_program/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/cairo_program/.vscode/settings.json b/cairo_program/.vscode/settings.json deleted file mode 100644 index edc55ce..0000000 --- a/cairo_program/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "snyk.advanced.autoSelectOrganization": true -} \ No newline at end of file diff --git a/cairo_program/README.md b/cairo_program/README.md deleted file mode 100644 index 8cf3016..0000000 --- a/cairo_program/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Cairo Program - -Welcome to **Cairo Bootcamp 6** — a hands-on, developer-focused program designed to help you learn Cairo from first principles and build real-world applications. This repository contains learning materials, examples, and exercises used throughout the bootcamp. - ---- - - - ---- - -## 📁 Repository Structure -. -├── src/ -├── starknet_contracts/ # Smart contracts (stateful logic) -├── exercises/ # Practice tasks and assignments -├── notes/ # Learning notes (felt, syntax, etc.) -└── README.md \ No newline at end of file diff --git a/cairo_program/Scarb.lock b/cairo_program/Scarb.lock deleted file mode 100644 index b4ff584..0000000 --- a/cairo_program/Scarb.lock +++ /dev/null @@ -1,6 +0,0 @@ -# Code generated by scarb DO NOT EDIT. -version = 1 - -[[package]] -name = "cairo_6" -version = "0.1.0" diff --git a/cairo_program/Scarb.toml b/cairo_program/Scarb.toml deleted file mode 100644 index b6c900a..0000000 --- a/cairo_program/Scarb.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "cairo_6" -version = "0.1.0" -edition = "2025_12" - -# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html - -[executable] - -[cairo] -enable-gas = false - -[dependencies] -cairo_execute = "2.18.0" - - diff --git a/cairo_program/src/bool.cairo b/cairo_program/src/bool.cairo deleted file mode 100644 index cafad1e..0000000 --- a/cairo_program/src/bool.cairo +++ /dev/null @@ -1,29 +0,0 @@ -#[executable] -fn main() { - let result: bool = is_adult(18); - println!("bool result = {}", result); - - let is_even_result: bool = is_even(17); - println!("result = {}", is_even_result); -} - -// determine boolean for adults -fn is_adult(x: u8) -> bool { - // let mut outcome: bool = false; - if x <= 18 { - // outcome = false; - return false; - } - // outcome = true; - return true; -} - - -// determine even numbers -fn is_even(x: u8) -> bool { - if x % 2 == 0 { - return true; - } - return false; -} - diff --git a/cairo_program/src/bytearray.cairo b/cairo_program/src/bytearray.cairo deleted file mode 100644 index 0c7f306..0000000 --- a/cairo_program/src/bytearray.cairo +++ /dev/null @@ -1,5 +0,0 @@ -#[executable] -fn main() { - let text: ByteArray = "We are writing Cairo in this session and it's going to be fun"; - println!("full text here: {}", text); -} \ No newline at end of file diff --git a/cairo_program/src/hello_world.cairo b/cairo_program/src/hello_world.cairo deleted file mode 100644 index 1739c6d..0000000 --- a/cairo_program/src/hello_world.cairo +++ /dev/null @@ -1,6 +0,0 @@ -#[executable] -fn main() { - let x: felt252 = 32; - println!("x is: {}", x); - println!("Hello, World!"); -} diff --git a/cairo_program/src/integer.cairo b/cairo_program/src/integer.cairo deleted file mode 100644 index 9501eca..0000000 --- a/cairo_program/src/integer.cairo +++ /dev/null @@ -1,20 +0,0 @@ -#[executable] -fn main() { - let result: u8 = add_num(5, 6); - println!("the sum of x & y is: {}", result); - assert(result == 11, 'invalid sum logic'); - - let sub_result: u8 = sub_num(10, 5); - println!("sub result is: {}", sub_result); - assert(sub_result == 5, 'invalid sub logic'); -} - -// addition logic -fn add_num(x: u8, y: u8) -> u8 { - x + y -} - -// subtraction logic -fn sub_num(x: u8, y: u8) -> u8 { - return x - y; -} diff --git a/cairo_program/src/lib.cairo b/cairo_program/src/lib.cairo deleted file mode 100644 index acc7644..0000000 --- a/cairo_program/src/lib.cairo +++ /dev/null @@ -1,5 +0,0 @@ -// mod hello_world; -// mod short_string; -// mod integer; -// mod bool; -mod bytearray; \ No newline at end of file diff --git a/cairo_program/src/short_string.cairo b/cairo_program/src/short_string.cairo deleted file mode 100644 index 6674470..0000000 --- a/cairo_program/src/short_string.cairo +++ /dev/null @@ -1,5 +0,0 @@ -#[executable] -fn main() { - let bootcamp_name: felt252 = 'Bootcamp 6.0'; - println!("bootcamp name is: {}", bootcamp_name); -} diff --git a/starknet_contracts/src/lib.cairo b/starknet_contracts/src/lib.cairo deleted file mode 100644 index f1b82bb..0000000 --- a/starknet_contracts/src/lib.cairo +++ /dev/null @@ -1,32 +0,0 @@ -/// Interface representing `HelloContract`. -/// This interface allows modification and retrieval of the contract's storage count. -#[starknet::interface] -pub trait ICounter { - /// Increase count. - fn increase_count(ref self: T, amount: u32); - /// Retrieve count. - fn get_count(self: @T) -> u32; -} - -/// Simple contract for managing count. -#[starknet::contract] -mod Counter { - use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; - - #[storage] - struct Storage { - count: u32, - } - - #[abi(embed_v0)] - impl CounterImpl of super::ICounter { - fn increase_count(ref self: ContractState, amount: u32) { - assert(amount != 0, 'Amount cannot be 0'); - self.count.write(self.count.read() + amount); - } - - fn get_count(self: @ContractState) -> u32 { - self.count.read() - } - } -}