From b821a825049c9b68c2e9e0ba1f131b05b7b637c2 Mon Sep 17 00:00:00 2001 From: Robert~ Date: Thu, 11 May 2023 12:51:01 +0200 Subject: [PATCH 01/11] Converting the ERC721 exercise to Cairo V1. --- .gitignore | 1 - Scarb.toml | 8 + cairo_project.toml | 2 + src/ERC721.cairo | 1 + src/ERC721/IERC721.cairo | 18 ++ src/README.md | 54 +++++ src/evaluator.cairo | 318 ++++++++++++++++++++++++++++++ src/lib.cairo | 9 + src/temp.md | 33 ++++ src/token.cairo | 5 + src/token/ERC20_base.cairo | 158 +++++++++++++++ src/token/IERC20.cairo | 18 ++ src/token/ITDERC20.cairo | 12 ++ src/token/TDERC20.cairo | 206 +++++++++++++++++++ src/utils.cairo | 9 + src/utils/Iplayers_registry.cairo | 16 ++ src/utils/ex00_base.cairo | 127 ++++++++++++ src/utils/helper.cairo | 36 ++++ src/utils/helper.py | 30 +++ src/utils/players_registry.cairo | 160 +++++++++++++++ src/utils/sample_name.json | 1 + src/utils/sample_symbol.json | 1 + 22 files changed, 1222 insertions(+), 1 deletion(-) create mode 100644 Scarb.toml create mode 100644 cairo_project.toml create mode 100644 src/ERC721.cairo create mode 100644 src/ERC721/IERC721.cairo create mode 100644 src/README.md create mode 100644 src/evaluator.cairo create mode 100644 src/lib.cairo create mode 100644 src/temp.md create mode 100644 src/token.cairo create mode 100644 src/token/ERC20_base.cairo create mode 100644 src/token/IERC20.cairo create mode 100644 src/token/ITDERC20.cairo create mode 100644 src/token/TDERC20.cairo create mode 100644 src/utils.cairo create mode 100644 src/utils/Iplayers_registry.cairo create mode 100644 src/utils/ex00_base.cairo create mode 100644 src/utils/helper.cairo create mode 100644 src/utils/helper.py create mode 100644 src/utils/players_registry.cairo create mode 100644 src/utils/sample_name.json create mode 100644 src/utils/sample_symbol.json diff --git a/.gitignore b/.gitignore index f635df3..117957b 100644 --- a/.gitignore +++ b/.gitignore @@ -136,4 +136,3 @@ dmypy.json goerli.deployments.txt Makefile - diff --git a/Scarb.toml b/Scarb.toml new file mode 100644 index 0000000..4978f43 --- /dev/null +++ b/Scarb.toml @@ -0,0 +1,8 @@ +[package] +name = "starknet_erc721" +version = "0.1.0" +description = "Workshop to learn the basics of ERC721." +homepage = "https://github.com/starknet-edu/starknet-erc721" + + +[[target.starknet-contract]] diff --git a/cairo_project.toml b/cairo_project.toml new file mode 100644 index 0000000..b4fc4ca --- /dev/null +++ b/cairo_project.toml @@ -0,0 +1,2 @@ +[crate_roots] +starknet_erc721 = "src" \ No newline at end of file diff --git a/src/ERC721.cairo b/src/ERC721.cairo new file mode 100644 index 0000000..6f4066f --- /dev/null +++ b/src/ERC721.cairo @@ -0,0 +1 @@ +mod IERC721; \ No newline at end of file diff --git a/src/ERC721/IERC721.cairo b/src/ERC721/IERC721.cairo new file mode 100644 index 0000000..aa63894 --- /dev/null +++ b/src/ERC721/IERC721.cairo @@ -0,0 +1,18 @@ +use starknet::ContractAddress; + +//################### +// IERC721 INTERFACE +//################### + +#[abi] +trait IERC721 { + fn get_name() -> felt252; + fn get_symbol() -> felt252; + fn owner_of(token_id: u256) -> ContractAddress; + fn balance_of(account: ContractAddress) -> u256; + fn mint(to: ContractAddress, token_id: u256); + fn burn(token_id: u256); + fn approve(to: ContractAddress, token_id: u256); + fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256); +} + diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..02d4ef1 --- /dev/null +++ b/src/README.md @@ -0,0 +1,54 @@ +## Tasks List + +Today, we are creating your first ERC721 from the ground up on Starknet. The ERC721 token standard stands for non-fungible tokens, also known as NFTs. + +The contract interface of the ERC721 that you will need to follow can be found in `src/IERC721.cairo`. Please ensure that all the function names adhere to the IERC721 standard. + +Now, let's get our hands dirty! + +## Part 1: Creating an ERC721 + +### Exercise 1 - Deploying and initilizing your ERC721 + +First exercise of this part is to create your ERC721 Contract and your constructor function. + +1. Create your initial ERC721 contract. You will need the following: + 1. a constructor function that takes the `name` and `symbol` as input and then initializes the contract with those inputs + 2. a `get_name()` to receive the name of the ERC721 + 3. a `get_symbol()` to receive the symbol of the ERC721 +2. Assign a user slot from the Evaluator contract by calling `assign_user_slot()` + 1. Check the `get_user_slot()` to receive your number + 2. Based on your `user_slot` number, check the `get_info_name()` and `get_info_symbol()` to receive your unique `name` and `symbol`. + 3. use these values to initialize your ERC721 +3. Deploy your contract on testnet + 1. make sure you use your given values based on the assigned user slot. +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_01_erc721_init()` to verify your contract and receive points. + +### Exercise 2 - Minting a token + +Here, we will focus on minting your first NFT. + +1. Create the `mint()` function that allows you to mint an NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Call `ex_02_erc721_mint()` to verify your contract and receive points. + +### Exercise 3 - Burning a token + +Here, we will focus on creating the burn function. + +1. Create the `burn()` function that allows you to burn an NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Send a token to the Evaluator contract or use the previous exercise to mint a new token. +5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. + +### Exercise 4 - Transfering a token + +Here, we will focus on creating the transfer function. + +1. Create the `transfer_from()` function that allows you to transfer the NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Call `ex_04_erc721_transfer()` to verify your contract and receive points. diff --git a/src/evaluator.cairo b/src/evaluator.cairo new file mode 100644 index 0000000..5ecd560 --- /dev/null +++ b/src/evaluator.cairo @@ -0,0 +1,318 @@ +// ######## ERC 721 evaluator +// Soundtrack https://www.youtube.com/watch?v=iuWa5wh8lG0 + +#[contract] +#[derive(Copy, Drop)] +mod Evaluator{ + + //////////////////////////////// + // Core Library Imports + //////////////////////////////// + use starknet::get_caller_address; + use starknet::get_contract_address; + use starknet::ContractAddress; + use starknet::contract_address::ContractAddressZeroable; + use array::ArrayTrait; + use option::OptionTrait; + use zeroable::Zeroable; + use traits::TryInto; + use traits::Into; + use integer::u256; + use integer::u256_from_felt252; + + + //////////////////////////////// + // Internal Imports + //////////////////////////////// + use starknet_erc721::utils::ex00_base::Ex00Base::distribute_points; + use starknet_erc721::utils::ex00_base::Ex00Base::validate_exercise; + use starknet_erc721::utils::ex00_base::Ex00Base::ex_initializer; + use starknet_erc721::utils::ex00_base::Ex00Base::update_class_hash_by_admin; + use starknet_erc721::utils::helper; + use starknet_erc721::ERC721::IERC721::IERC721Dispatcher; + use starknet_erc721::ERC721::IERC721::IERC721DispatcherTrait; + + //////////////////////////////// + // Storage + //////////////////////////////// + struct Storage{ + user_slots: LegacyMap::, + names_mapped: LegacyMap::, + symbols_mapped: LegacyMap::, + was_initialized: LegacyMap::, + next_slot: u128, + player_exercise_solution_storage: LegacyMap::, + has_been_paired: LegacyMap::, + } + + //////////////////////////////// + // CONSTANTS + //////////////////////////////// + const USER_SLOT_LIMIT: u128 = 99_u128; + + + //////////////////////////////// + // Constructor + //////////////////////////////// + #[constructor] + fn constructor( + _tderc20_address: ContractAddress, _players_registry: ContractAddress, _workshop_id: u128, _exercise_id: u128 + ) { + ex_initializer(_tderc20_address, _players_registry, _workshop_id, _exercise_id); + } + + //////////////////////////////// + // View Functions + //////////////////////////////// + #[view] + fn get_user_slot(account: ContractAddress) -> u128 { + user_slots::read(account) + } + + #[view] + fn player_exercise_solution(player_address: ContractAddress) -> ContractAddress { + player_exercise_solution_storage::read(player_address) + } + + #[view] + fn get_info_name(user_slot: u128) -> felt252 { + names_mapped::read(user_slot) + } + + #[view] + fn get_info_symbol(user_slot: u128) -> felt252 { + symbols_mapped::read(user_slot) + } + + //////////////////////////////// + // External Functions + //////////////////////////////// + #[external] + fn ex_01_erc721_init(){ + + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // Retrieve name and symbol from the submitted exercise + let name = IERC721Dispatcher{contract_address: submitted_exercise_address}.get_name(); + let symbol = IERC721Dispatcher{contract_address: submitted_exercise_address}.get_symbol(); + + // Retrieve assigned user slot for the caller address + let _user_slot = user_slots::read(sender_address); + + // Retrieve assigned variable based on the user slot + let assigned_name = get_info_name(_user_slot); + let assigned_symbol = get_info_symbol(_user_slot); + + // Checking if the name/symbol are correctly initialized + assert(name == assigned_name, 'NAME_INCORRECT'); + assert(symbol == assigned_symbol, 'SYMBOL_INCORRECT'); + + // 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] + fn ex_02_erc721_mint(token_id: u256){ + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // Retrieve the evaluator address + let contract_address = get_contract_address(); + + // minting token_id + IERC721Dispatcher{contract_address: submitted_exercise_address}.mint(contract_address, token_id); + + // Retrieve the owner of token_id + let check_owner_of = IERC721Dispatcher{contract_address: submitted_exercise_address}.owner_of(token_id); + + // Checking if owner of the token_id is the evaluator + assert(check_owner_of == contract_address, 'NOT_THE_OWNER'); + + // 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] + fn ex_03_erc721_burn(token_id: u256){ + + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // Get the evaluator address + let contract_address = get_contract_address(); + + // Retrieve balance before burn + let balance_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(contract_address); + + // check if burn method works + IERC721Dispatcher{contract_address: submitted_exercise_address}.burn(token_id); + + // Retrieve balance after burn + let balance_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(contract_address); + + // Checking if owner of the token_id is the evaluator + assert(balance_c2 == balance_c1 - u256_from_felt252(1), 'BALANCE_INCORRECT'); + + // 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] + fn ex_04_erc721_transfer(token_id: u256){ + + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // Get the evaluator address + let contract_address = get_contract_address(); + + // Retrieve balance and owner before transfer + let balance_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(sender_address); + let owner_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.owner_of(token_id); + + // approve for transfer + IERC721Dispatcher{contract_address: submitted_exercise_address}.approve(sender_address, token_id); + + // approve for transfer + IERC721Dispatcher{contract_address: submitted_exercise_address}.transfer_from(contract_address, sender_address, token_id); + + // Retrieve balance and owner after transfer + let balance_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(sender_address); + let owner_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.owner_of(token_id); + + // Checks + assert(balance_c2 == balance_c1 + u256_from_felt252(1), 'WRONG_BALANCE'); + assert(owner_c1 != owner_c2, 'OWNER_IS_THE_SAME'); + assert(owner_c2 == sender_address, 'OWNER_WRONG'); + + // 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] + fn submit_exercise(exercise_address: ContractAddress){ + // Retrieve caller address + let sender_address = get_caller_address(); + + // Check if exercise has been submited before. + assert(has_been_paired::read(exercise_address) != true, 'SOLUTION_SUBMITED_ALREADY'); + + // Store exercise address + player_exercise_solution_storage::write(sender_address, exercise_address); + has_been_paired::write(exercise_address, true); + + } + + // This function is used to assign a slot to a user and to update the next slot + #[external] + fn assign_user_slot() { + // Retrieve caller address + let sender_address: ContractAddress = get_caller_address(); + + let _next_slot = next_slot::read(); + + if _next_slot == USER_SLOT_LIMIT { + next_slot::write(0_u128); + } + + user_slots::write(sender_address, next_slot::read() + 1_u128); + next_slot::write(next_slot::read() + 1_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); + } + #[external] + fn set_random_names(values: Array::) { + // Check if the random values were already initialized + let was_initialized_read = was_initialized::read(0_u8); + assert(was_initialized_read != true, 'NOT_INITIALISED'); + + let mut idx: u128 = 0_u128; + set_a_random_name(idx, values); + + // Mark that names store was initialized + was_initialized::write(0_u8, true); + } + + #[external] + fn set_random_symbols(values: Array::) { + // Check if the random values were already initialized + let was_initialized_read = was_initialized::read(1_u8); + assert(was_initialized_read != true, 'NOT_INITIALISED'); + + let mut idx: u128 = 0_u128; + set_a_random_symbol(idx, values); + + // Mark that symbols store was initialized + was_initialized::write(1_u8, true); + } + + fn set_a_random_name(mut idx: u128, mut values: Array::) { + helper::check_gas(); + if !values.is_empty() { + names_mapped::write(idx, values.pop_front().unwrap()); + idx = idx + 1_u128; + set_a_random_name(idx, values); + } + } + + fn set_a_random_symbol(mut idx: u128, mut values: Array::) { + helper::check_gas(); + if !values.is_empty() { + symbols_mapped::write(idx, values.pop_front().unwrap()); + idx = idx + 1_u128; + set_a_random_symbol(idx, values); + } + } + + fn verify() -> ContractAddress { + // Retrieve caller address + let sender_address = get_caller_address(); + + // Retrieve exercise address + let submitted_exercise_address = player_exercise_solution_storage::read(sender_address); + + // Reading the slot assigned to the caller address in the mapping user_slots. + // The value was assigned when assign_user_slot() was called by the user (see below) and is stored in the mapping user_slots + let user_slot = user_slots::read(sender_address); + // Checking that the user has a slot assigned to they (i.e. that he called assign_user_slot() before) + assert(user_slot != 0_u128, 'ASSIGN_USER_SLOT_FIRST'); + + // Check if solution has been submitted + assert(!submitted_exercise_address.is_zero(), 'SOLUTION_NOT_SUBMITTED'); + + // returning the submitted exercise + submitted_exercise_address + } + +} diff --git a/src/lib.cairo b/src/lib.cairo new file mode 100644 index 0000000..3b90756 --- /dev/null +++ b/src/lib.cairo @@ -0,0 +1,9 @@ +// Utils +mod utils; + +// Token module +mod ERC721; +mod token; + +// Contract +mod evaluator; diff --git a/src/temp.md b/src/temp.md new file mode 100644 index 0000000..4003932 --- /dev/null +++ b/src/temp.md @@ -0,0 +1,33 @@ +# Cheatsheet + +## Deploying Exercise: + +| Contract | Class hash | Deployed contract | Permission | +| --------- | ---------- | ----------------- | ---------- | +| Evaluator | TBA | TBA | TBA | + +## Useful comands: + +Deploying players registry and ERC20 and checking admin is registered + +``` +# Players registry +TBA +``` + +### Declaring Evaluator + +### Setting up random variables + +Setting random names: + +``` +starknet invoke --function set_random_names --address 0x039930ebf6ecb2d31b60f24e5729de95f63df86556cf20e163ed94213ce7000d --account version_2 --max_fee 10000000000000000 --input 100 1477539817190980062013511436222722368611442480 1477539817190980062013511436222722368611442481 1477539817190980062013511436222722368611442482 1477539817190980062013511436222722368611442483 1477539817190980062013511436222722368611442484 1477539817190980062013511436222722368611442485 1477539817190980062013511436222722368611442486 1477539817190980062013511436222722368611442487 1477539817190980062013511436222722368611442488 1477539817190980062013511436222722368611442489 378250193200890895875458927673016926364529275184 378250193200890895875458927673016926364529275185 378250193200890895875458927673016926364529275186 378250193200890895875458927673016926364529275187 378250193200890895875458927673016926364529275188 378250193200890895875458927673016926364529275189 378250193200890895875458927673016926364529275190 378250193200890895875458927673016926364529275191 378250193200890895875458927673016926364529275192 378250193200890895875458927673016926364529275193 378250193200890895875458927673016926364529275440 378250193200890895875458927673016926364529275441 378250193200890895875458927673016926364529275442 378250193200890895875458927673016926364529275443 378250193200890895875458927673016926364529275444 378250193200890895875458927673016926364529275445 378250193200890895875458927673016926364529275446 378250193200890895875458927673016926364529275447 378250193200890895875458927673016926364529275448 378250193200890895875458927673016926364529275449 378250193200890895875458927673016926364529275696 378250193200890895875458927673016926364529275697 378250193200890895875458927673016926364529275698 378250193200890895875458927673016926364529275699 378250193200890895875458927673016926364529275700 378250193200890895875458927673016926364529275701 378250193200890895875458927673016926364529275702 378250193200890895875458927673016926364529275703 378250193200890895875458927673016926364529275704 378250193200890895875458927673016926364529275705 378250193200890895875458927673016926364529275952 378250193200890895875458927673016926364529275953 378250193200890895875458927673016926364529275954 378250193200890895875458927673016926364529275955 378250193200890895875458927673016926364529275956 378250193200890895875458927673016926364529275957 378250193200890895875458927673016926364529275958 378250193200890895875458927673016926364529275959 378250193200890895875458927673016926364529275960 378250193200890895875458927673016926364529275961 378250193200890895875458927673016926364529276208 378250193200890895875458927673016926364529276209 378250193200890895875458927673016926364529276210 378250193200890895875458927673016926364529276211 378250193200890895875458927673016926364529276212 378250193200890895875458927673016926364529276213 378250193200890895875458927673016926364529276214 378250193200890895875458927673016926364529276215 378250193200890895875458927673016926364529276216 378250193200890895875458927673016926364529276217 378250193200890895875458927673016926364529276464 378250193200890895875458927673016926364529276465 378250193200890895875458927673016926364529276466 378250193200890895875458927673016926364529276467 378250193200890895875458927673016926364529276468 378250193200890895875458927673016926364529276469 378250193200890895875458927673016926364529276470 378250193200890895875458927673016926364529276471 378250193200890895875458927673016926364529276472 378250193200890895875458927673016926364529276473 378250193200890895875458927673016926364529276720 378250193200890895875458927673016926364529276721 378250193200890895875458927673016926364529276722 378250193200890895875458927673016926364529276723 378250193200890895875458927673016926364529276724 378250193200890895875458927673016926364529276725 378250193200890895875458927673016926364529276726 378250193200890895875458927673016926364529276727 378250193200890895875458927673016926364529276728 378250193200890895875458927673016926364529276729 378250193200890895875458927673016926364529276976 378250193200890895875458927673016926364529276977 378250193200890895875458927673016926364529276978 378250193200890895875458927673016926364529276979 378250193200890895875458927673016926364529276980 378250193200890895875458927673016926364529276981 378250193200890895875458927673016926364529276982 378250193200890895875458927673016926364529276983 378250193200890895875458927673016926364529276984 378250193200890895875458927673016926364529276985 378250193200890895875458927673016926364529277232 378250193200890895875458927673016926364529277233 378250193200890895875458927673016926364529277234 378250193200890895875458927673016926364529277235 378250193200890895875458927673016926364529277236 378250193200890895875458927673016926364529277237 378250193200890895875458927673016926364529277238 378250193200890895875458927673016926364529277239 378250193200890895875458927673016926364529277240 378250193200890895875458927673016926364529277241 +``` + +Setting random symbols: + +``` +starknet invoke --function set_random_symbols --address 0x039930ebf6ecb2d31b60f24e5729de95f63df86556cf20e163ed94213ce7000d --account version_2 --max_fee 10000000000000000 --input 100 18668896499556144 18668896499556145 18668896499556146 18668896499556147 18668896499556148 18668896499556149 18668896499556150 18668896499556151 18668896499556152 18668896499556153 4779237503886373168 4779237503886373169 4779237503886373170 4779237503886373171 4779237503886373172 4779237503886373173 4779237503886373174 4779237503886373175 4779237503886373176 4779237503886373177 4779237503886373424 4779237503886373425 4779237503886373426 4779237503886373427 4779237503886373428 4779237503886373429 4779237503886373430 4779237503886373431 4779237503886373432 4779237503886373433 4779237503886373680 4779237503886373681 4779237503886373682 4779237503886373683 4779237503886373684 4779237503886373685 4779237503886373686 4779237503886373687 4779237503886373688 4779237503886373689 4779237503886373936 4779237503886373937 4779237503886373938 4779237503886373939 4779237503886373940 4779237503886373941 4779237503886373942 4779237503886373943 4779237503886373944 4779237503886373945 4779237503886374192 4779237503886374193 4779237503886374194 4779237503886374195 4779237503886374196 4779237503886374197 4779237503886374198 4779237503886374199 4779237503886374200 4779237503886374201 4779237503886374448 4779237503886374449 4779237503886374450 4779237503886374451 4779237503886374452 4779237503886374453 4779237503886374454 4779237503886374455 4779237503886374456 4779237503886374457 4779237503886374704 4779237503886374705 4779237503886374706 4779237503886374707 4779237503886374708 4779237503886374709 4779237503886374710 4779237503886374711 4779237503886374712 4779237503886374713 4779237503886374960 4779237503886374961 4779237503886374962 4779237503886374963 4779237503886374964 4779237503886374965 4779237503886374966 4779237503886374967 4779237503886374968 4779237503886374969 4779237503886375216 4779237503886375217 4779237503886375218 4779237503886375219 4779237503886375220 4779237503886375221 4779237503886375222 4779237503886375223 4779237503886375224 4779237503886375225 + +``` diff --git a/src/token.cairo b/src/token.cairo new file mode 100644 index 0000000..9f60e2d --- /dev/null +++ b/src/token.cairo @@ -0,0 +1,5 @@ +mod ITDERC20; +mod IERC20; + +mod ERC20_base; +mod TDERC20; diff --git a/src/token/ERC20_base.cairo b/src/token/ERC20_base.cairo new file mode 100644 index 0000000..8978c89 --- /dev/null +++ b/src/token/ERC20_base.cairo @@ -0,0 +1,158 @@ +//////////////////////////////// +// ERC20Base +// A Base ERC20 contract to implement ERC20 standarded methods +// such as `transfer`, `transfer_from`, `mint`, 'burn', 'approve' etc. +//////////////////////////////// + +#[contract] +mod ERC20Base { + // Core library Imports + use starknet::get_caller_address; + use zeroable::Zeroable; + use starknet::contract_address_const; + use starknet::ContractAddress; + use starknet::ContractAddressZeroable; + use traits::Into; + use traits::TryInto; + use array::ArrayTrait; + use option::OptionTrait; + use integer::u256_from_felt252; + + // + // Declaring storage vars + // Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity + // + // This variable is a felt and is called my_secret_value_storage. It is stored in the contract's Storage struct + // From within a smart contract, it can be read with my_secret_value_storage::read() or written to with my_secret_value_storage::write() + + struct Storage { + name: felt252, + symbol: felt252, + decimals: u8, + total_supply: u256, + balances: LegacyMap::, + allowances: LegacyMap::<(ContractAddress, ContractAddress), u256>, + } + + fn ERC20_name() -> felt252 { + name::read() + } + + fn ERC20_symbol() -> felt252 { + symbol::read() + } + + fn ERC20_decimals() -> u8 { + decimals::read() + } + + fn ERC20_totalSupply() -> u256 { + total_supply::read() + } + + fn ERC20_balanceOf(account: ContractAddress) -> u256 { + balances::read(account) + } + + fn ERC20_allowance(owner: ContractAddress, spender: ContractAddress) -> u256 { + allowances::read((owner, spender)) + } + + //////////////////////////////// + // Internal Constructor + //////////////////////////////// + fn ERC20_initializer( + name_: felt252, symbol_: felt252, decimals_: u8, initial_supply: u256, recipient: ContractAddress + ) { + name::write(name_); + symbol::write(symbol_); + decimals::write(decimals_); + ERC20_mint(recipient, initial_supply); + } + + + //////////////////////////////// + // Internal FUNCTIONS + //////////////////////////////// + fn ERC20_transfer(recipient: ContractAddress, amount: u256) { + let sender = get_caller_address(); + transfer_helper(sender, recipient, amount); + } + + fn ERC20_transferFrom(sender: ContractAddress, recipient: ContractAddress, amount: u256) { + let caller = get_caller_address(); + spend_allowance(sender, caller, amount); + transfer_helper(sender, recipient, amount); + } + + fn ERC20_approve(spender: ContractAddress, amount: u256) { + let caller = get_caller_address(); + approve_helper(caller, spender, amount); + } + + fn ERC20_increaseAllowance(spender: ContractAddress, added_value: u256) { + let caller = get_caller_address(); + approve_helper(caller, spender, allowances::read((caller, spender)) + added_value); + } + + fn ERC20_decreaseAllowance(spender: ContractAddress, subtracted_value: u256) { + let caller = get_caller_address(); + approve_helper(caller, spender, allowances::read((caller, spender)) - subtracted_value); + } + + fn ERC20_mint(recipient: ContractAddress, amount: u256) { + assert(!recipient.is_zero(), 'ERC20: mint to the 0 address'); + assert(amount >= u256_from_felt252(0), 'ZERO_AMOUNT'); + + let balance: u256 = balances::read(recipient); + // overflow is not possible because sum is guaranteed to be less than total supply + // which we check for overflow below + let new_balance: u256 = balance + amount; + balances::write(recipient, new_balance); + + let supply: u256 = total_supply::read(); + let new_supply: u256 = supply + amount; + + total_supply::write(new_supply); + } + + fn ERC20_burn(account: ContractAddress, amount: u256) { + assert(!account.is_zero(), 'ERC20: burn to the 0 address'); + assert(amount > u256_from_felt252(0), 'ZERO_AMOUNT'); + + let balance: u256 = balances::read(account); + assert(balance >= amount, 'ERC20: burn amount exceeds'); + + // overflow is not possible because sum is guaranteed to be less than total supply + // which we check for overflow below + let new_balance: u256 = balance - amount; + balances::write(account, new_balance); + + let supply: u256 = total_supply::read(); + let new_supply: u256 = supply - amount; + + total_supply::write(new_supply); + } + + fn transfer_helper(sender: ContractAddress, recipient: ContractAddress, amount: u256) { + assert(!sender.is_zero(), 'ERC20: transfer from 0'); + assert(!recipient.is_zero(), 'ERC20: transfer to 0'); + balances::write(sender, balances::read(sender) - amount); + balances::write(recipient, balances::read(recipient) + amount); + } + + fn spend_allowance(owner: ContractAddress, spender: ContractAddress, amount: u256) { + let current_allowance = allowances::read((owner, spender)); + let ONES_MASK = 0xffffffffffffffffffffffffffffffff_u128; + let is_unlimited_allowance = + current_allowance.low == ONES_MASK & current_allowance.high == ONES_MASK; + if !is_unlimited_allowance { + approve_helper(owner, spender, current_allowance - amount); + } + } + + fn approve_helper(owner: ContractAddress, spender: ContractAddress, amount: u256) { + assert(!spender.is_zero(), 'ERC20: approve from 0'); + allowances::write((owner, spender), amount); + } +} diff --git a/src/token/IERC20.cairo b/src/token/IERC20.cairo new file mode 100644 index 0000000..f4c674d --- /dev/null +++ b/src/token/IERC20.cairo @@ -0,0 +1,18 @@ +use starknet::ContractAddress; + +//################### +// IERC20 INTERFACE +//################### + +#[abi] +trait IERC20 { + fn name() -> felt252; + fn symbol() -> felt252; + fn decimals() -> u8; + fn totalSupply() -> u256; + fn balanceOf(account: ContractAddress) -> u256; + fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256; + fn transfer(recipient: ContractAddress, amount: u256); + fn transferFrom(sender: ContractAddress, recipient: ContractAddress, amount: u256); + fn approve(spender: ContractAddress, amount: u256); +} diff --git a/src/token/ITDERC20.cairo b/src/token/ITDERC20.cairo new file mode 100644 index 0000000..c3882a4 --- /dev/null +++ b/src/token/ITDERC20.cairo @@ -0,0 +1,12 @@ +use starknet::ContractAddress; +//################### +// ITDERC20 INTERFACE +//################### +#[abi] +trait ITDERC20 { + fn distribute_points(to: ContractAddress, amount: u128); + fn remove_points(to: ContractAddress, amount: u128); + fn set_teacher(account: ContractAddress, permission: bool); + fn is_teacher_or_exercise(account: ContractAddress) -> bool; + +} diff --git a/src/token/TDERC20.cairo b/src/token/TDERC20.cairo new file mode 100644 index 0000000..32709f5 --- /dev/null +++ b/src/token/TDERC20.cairo @@ -0,0 +1,206 @@ +//////////////////////////////// +// TDERC20 +// Main ERC20 contract to utilise ERC20_base contracts +// The contract is used to distribute points etc. +//////////////////////////////// + +#[contract] +mod TDERC20 { + // Core library Imports + use starknet::get_caller_address; + use zeroable::Zeroable; + use starknet::contract_address_const; + use starknet::ContractAddress; + use traits::Into; + use traits::TryInto; + use array::ArrayTrait; + use option::OptionTrait; + use starknet::ClassHash; + use starknet::syscalls::replace_class_syscall; + use starknet::class_hash::Felt252TryIntoClassHash; + + + // Internal Imports + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_name; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_symbol; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_totalSupply; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_decimals; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_balanceOf; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_allowance; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_mint; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_burn; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_initializer; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_approve; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_increaseAllowance; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_decreaseAllowance; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transfer; + use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transferFrom; + use starknet_erc721::utils::helper; + + struct Storage { + is_transferable_storage: bool, + teachers_and_exercises_accounts: LegacyMap, + } + + //////////////////////////////// + // Events + //////////////////////////////// + #[event] + fn Transfer(from: ContractAddress, to: ContractAddress, value: u256) {} + + #[event] + fn Approval(owner: ContractAddress, spender: ContractAddress, value: u256) {} + + //////////////////////////////// + // View FUNCTIONS + //////////////////////////////// + #[view] + fn is_transferable() -> bool { + is_transferable_storage::read() + } + + #[view] + fn name() -> felt252 { + ERC20_name() + } + + #[view] + fn symbol() -> felt252 { + ERC20_symbol() + } + + #[view] + fn decimals() -> u8 { + ERC20_decimals() + } + + #[view] + fn totalSupply() -> u256 { + ERC20_totalSupply() + } + + #[view] + fn balanceOf(account: ContractAddress) -> u256 { + ERC20_balanceOf(account) + } + + #[view] + fn allowance(owner: ContractAddress, spender: ContractAddress) -> u256 { + ERC20_allowance(owner, spender) + } + + #[view] + fn is_teacher_or_exercise(account: ContractAddress) -> bool { + teachers_and_exercises_accounts::read(account) + } + + //////////////////////////////// + // Constructor + //////////////////////////////// + #[constructor] + fn constructor( + name_: felt252, symbol_: felt252, decimals_: u8, initial_supply: u256, recipient: ContractAddress, owner: ContractAddress + ) { + ERC20_initializer(name_, symbol_, decimals_, initial_supply, recipient); + teachers_and_exercises_accounts::write(owner, true); + Transfer(contract_address_const::<0>(), recipient, initial_supply); + } + + + //////////////////////////////// + // EXTERNAL FUNCTIONS + //////////////////////////////// + #[external] + fn transfer(recipient: ContractAddress, amount: u256) -> bool { + _is_transferable(); + ERC20_transfer(recipient, amount); + return true; + } + + #[external] + fn transferFrom(sender: ContractAddress, recipient: ContractAddress, amount: u256) -> bool { + _is_transferable(); + ERC20_transferFrom(sender, recipient, amount); + Transfer(sender, recipient, amount); + return true; + } + + #[external] + fn approve(spender: ContractAddress, amount: u256) -> bool { + ERC20_approve(spender, amount); + let owner: ContractAddress = get_caller_address(); + Approval(owner, spender, amount); + return true; + } + + #[external] + fn increaseAllowance(spender: ContractAddress, added_value: u256) -> bool { + ERC20_increaseAllowance(spender, added_value); + return true; + } + + #[external] + fn decreaseAllowance(spender: ContractAddress, subtracted_value: u256) -> bool { + ERC20_decreaseAllowance(spender, subtracted_value); + return true; + } + + #[external] + fn distribute_points(to: ContractAddress, amount: u128) { + only_teacher_or_exercise(); + ERC20_mint(to, u256 { low: amount, high: 0_u128 }); + } + + #[external] + fn remove_points(to: ContractAddress, amount: u128) { + only_teacher_or_exercise(); + ERC20_burn(to, u256 { low: amount, high: 0_u128 }); + } + + #[external] + fn set_teachers(accounts: Array::, permissions: Array::) { + only_teacher_or_exercise(); + set_single_teacher(accounts, permissions); + } + + fn set_single_teacher(mut accounts: Array::,mut permissions: Array::) { + helper::check_gas(); + if !accounts.is_empty() { + teachers_and_exercises_accounts::write(accounts.pop_front().unwrap(), permissions.pop_front().unwrap()); + set_single_teacher(accounts, permissions); + } + } + + #[external] + fn set_teacher(account: ContractAddress, permission: bool) { + only_teacher_or_exercise(); + teachers_and_exercises_accounts::write(account, permission); + } + + #[external] + fn set_transferable(permission: bool) { + only_teacher_or_exercise(); + is_transferable_storage::write(permission); + return (); + } + + //////////////////////////////// + // INTERNAL FUNCTIONS + //////////////////////////////// + fn only_teacher_or_exercise() { + let caller = get_caller_address(); + let permission = teachers_and_exercises_accounts::read(caller); + assert(permission == true, 'NO_PERMISSION'); + } + + fn _is_transferable() { + let permission = is_transferable_storage::read(); + assert(permission == true, 'NOT_TRANSFERABLE'); + } + #[external] + fn update_class_hash_by_admin(class_hash_in_felt: felt252) { + only_teacher_or_exercise(); + let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); + replace_class_syscall(class_hash); + } +} diff --git a/src/utils.cairo b/src/utils.cairo new file mode 100644 index 0000000..4a74a0d --- /dev/null +++ b/src/utils.cairo @@ -0,0 +1,9 @@ +mod helper; + + +mod Iplayers_registry; + +mod ex00_base; + +mod players_registry; + diff --git a/src/utils/Iplayers_registry.cairo b/src/utils/Iplayers_registry.cairo new file mode 100644 index 0000000..a24bfa2 --- /dev/null +++ b/src/utils/Iplayers_registry.cairo @@ -0,0 +1,16 @@ +use starknet::ContractAddress; + +//////////////////////////////// +// Iplayers_registry INTERFACE +//////////////////////////////// +#[abi] +trait Iplayers_registry { + fn has_validated_exercise(account: ContractAddress, workshop: u128, exercise: u128) -> bool; + fn is_exercise_or_admin(account: ContractAddress) -> bool; + fn next_player_rank() -> u128; + fn players_registry(rank: u128) -> ContractAddress; + fn player_ranks(account: ContractAddress) -> u128; + fn set_exercise_or_admin(account: ContractAddress, permission: bool); + fn set_exercises_or_admins(accounts: Array::); + fn validate_exercise(account: ContractAddress, workshop: u128, exercise: u128); +} diff --git a/src/utils/ex00_base.cairo b/src/utils/ex00_base.cairo new file mode 100644 index 0000000..0f2dc2e --- /dev/null +++ b/src/utils/ex00_base.cairo @@ -0,0 +1,127 @@ +//////////////////////////////// +// Ex11Base +// A Base contract from which other contracts can import major functions +// such as `validate_exercise`, `distribute_points` +//////////////////////////////// + + +#[contract] +mod Ex00Base { + // Core Library Imports + use starknet::get_caller_address; + use zeroable::Zeroable; + use starknet::ContractAddress; + use starknet::ContractAddressZeroable; + use starknet::syscalls::replace_class_syscall; + use starknet::ClassHash; + use starknet::class_hash::Felt252TryIntoClassHash; + use integer::u256_from_felt252; + use traits::Into; + use traits::TryInto; + use array::ArrayTrait; + use option::OptionTrait; + + // Internal Imports + use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcherTrait; + use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcher; + use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; + use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; + + const Decimals: u128 = 1000000000000000000_u128; + + + //////////////////////////////// + // 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() + } + + #[view] + fn players_registry() -> ContractAddress { + players_registry_storage::read() + } + + #[view] + fn workshop_id() -> u128 { + workshop_id_storage::read() + } + + #[view] + fn exercise_id() -> u128 { + exercise_id_storage::read() + } + + #[view] + fn has_validated_exercise(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(); + + 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); + } + + //////////////////////////////// + // Internal Functions + //////////////////////////////// + fn distribute_points(to: ContractAddress, amount: u128) { + // Retrieving contract address from storage + let tderc20_address = tderc20_address_storage::read(); + let points_to_credit: u128 = amount * Decimals; + + ITDERC20Dispatcher{contract_address: tderc20_address} + .distribute_points(to, points_to_credit); + } + + fn validate_exercise(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 has_current_user_validated_exercise = + 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); + } + + fn update_class_hash_by_admin(class_hash_in_felt: felt252) { + let players_registry = 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); + + assert (is_admin == true, 'CALLER_NO_ADMIN_RIGHTS'); + let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); + replace_class_syscall(class_hash); + } +} diff --git a/src/utils/helper.cairo b/src/utils/helper.cairo new file mode 100644 index 0000000..188c862 --- /dev/null +++ b/src/utils/helper.cairo @@ -0,0 +1,36 @@ +use array::ArrayTrait; +use option::OptionTrait; +use traits::TryInto; +use traits::Into; +use gas::get_builtin_costs; + +const DECIMALS_18: u128 = 1000000000000000000_u128; +const DECIMALS_12: u128 = 1000000000000_u128; +const DECIMALS_6: u128 = 1000000_u128; + +// Fake macro to compute gas left +// TODO: Remove when automatically handled by compiler. +#[inline(always)] +fn check_gas() { + match gas::withdraw_gas_all(get_builtin_costs()) { + Option::Some(_) => {}, + Option::None(_) => { + let mut data = ArrayTrait::new(); + data.append('Out of gas'); + panic(data); + } + } +} + +// TODO: Use Math.pow() once cairo supports the function +// For the simplicity, We dont want to include a third party lib to do pow() +#[inline(always)] +fn get_token_in_decimals(decimals: u8) -> u128 { + if decimals == 18_u8 { + DECIMALS_18 + } else if decimals == 12_u8 { + DECIMALS_12 + } else { + DECIMALS_6 + } +} diff --git a/src/utils/helper.py b/src/utils/helper.py new file mode 100644 index 0000000..949c41e --- /dev/null +++ b/src/utils/helper.py @@ -0,0 +1,30 @@ +import json + +MAX_LEN_FELT = 31 + +def str_to_felt(text): + if len(text) > MAX_LEN_FELT: + raise Exception("Text length too long to convert to felt.") + return int.from_bytes(text.encode(), "big") + +data_name = [] +data_symbol = [] + +for i in range(0, 100): + data_name.append(str_to_felt(f"BASECAMP_04_TOKEN_{i}")) + data_symbol.append(str_to_felt(f"BSC04_{i}")) + + +print(len(data_symbol)) +print(data_name) +print(data_symbol) + +with open('sample_name.json', 'w') as f: + json.dump(data_name, f, separators=(" ", ":")) + +with open('sample_symbol.json', 'w') as f: + json.dump(data_symbol, f, separators=(" ", ":")) + +print("Sample data saved.") + + diff --git a/src/utils/players_registry.cairo b/src/utils/players_registry.cairo new file mode 100644 index 0000000..1c0f09d --- /dev/null +++ b/src/utils/players_registry.cairo @@ -0,0 +1,160 @@ +//////////////////////////////// +// PlayersRegistry +// A contract to record all addresses who participated, and which exercises and workshops they completed +//////////////////////////////// + + +#[contract] +mod PlayersRegistry { + // Core Library Imports + use starknet::get_caller_address; + use zeroable::Zeroable; + use starknet::ContractAddress; + use starknet::ContractAddressZeroable; + use traits::Into; + use traits::TryInto; + use array::ArrayTrait; + use option::OptionTrait; + use starknet::ClassHash; + use starknet::syscalls::replace_class_syscall; + use starknet::class_hash::Felt252TryIntoClassHash; + use core::hash::TupleSize3LegacyHash; + + // Internal Imports + use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcherTrait; + use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcher; + use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; + use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; + use starknet_erc721::utils::helper; + + //////////////////////////////// + // STORAGE + //////////////////////////////// + struct Storage { + has_validated_exercise_storage: LegacyMap::<(ContractAddress, u128, u128), bool>, + exercises_and_admins_accounts: LegacyMap::, + next_player_rank: u128, + players_registry: LegacyMap::, + players_ranks_storage: LegacyMap::, + } + + //////////////////////////////// + // View Functions + //////////////////////////////// + #[view] + fn has_validated_exercise(account: ContractAddress, workshop: u128, exercise: u128) -> bool { + has_validated_exercise_storage::read((account, workshop, exercise)) + } + + #[view] + fn is_exercise_or_admin(account: ContractAddress) -> bool { + exercises_and_admins_accounts::read(account) + } + + #[view] + fn get_next_player_rank() -> u128 { + next_player_rank::read() + } + + #[view] + fn get_players_registry(rank: u128) -> ContractAddress { + players_registry::read(rank) + } + + #[view] + fn players_ranks(account: ContractAddress) -> u128 { + players_ranks_storage::read(account) + } + + //////////////////////////////// + // Events + //////////////////////////////// + #[event] + fn Modificate_Exercise_Or_Admin(account: ContractAddress, permission: bool) {} + + #[event] + fn New_Player(account: ContractAddress, rank: u128) {} + + #[event] + fn New_Validation(account: ContractAddress, workshop: u128, exercise: u128) {} + + //////////////////////////////// + // Constructor + //////////////////////////////// + #[constructor] + fn constructor(first_admin: ContractAddress) { + exercises_and_admins_accounts::write(first_admin, true); + Modificate_Exercise_Or_Admin(first_admin, true); + next_player_rank::write(1_u128); + } + + //////////////////////////////// + // External Functions + //////////////////////////////// + #[external] + fn set_exercise_or_admin(account: ContractAddress, permission: bool) { + only_exercise_or_admin(); + exercises_and_admins_accounts::write(account, permission); + Modificate_Exercise_Or_Admin(account, permission); + } + #[external] + fn set_exercises_or_admins(accounts: Array::, permissions: Array::) { + only_exercise_or_admin(); + set_single_exercise_or_admin(accounts, permissions); + } + + fn set_single_exercise_or_admin(mut accounts: Array::,mut permissions: Array::) { + helper::check_gas(); + if !accounts.is_empty() { + exercises_and_admins_accounts::write(accounts.pop_front().unwrap(), permissions.pop_front().unwrap()); + set_single_exercise_or_admin(accounts, permissions); + } + } + #[external] + fn update_class_hash_by_admin(class_hash_in_felt: felt252) { + only_exercise_or_admin(); + let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); + replace_class_syscall(class_hash); + } + + #[external] + fn validate_exercise(account: ContractAddress, workshop: u128, exercise: u128) { + only_exercise_or_admin(); + // Checking if the user already validated this exercise + let is_validated = has_validated_exercise_storage::read( + (account, workshop, exercise) + ); + + assert(is_validated == false, 'USER_VALIDATED'); + + // Marking the exercise as completed + has_validated_exercise_storage::write((account, workshop, exercise), true); + New_Validation(account, workshop, exercise); + + // Recording player if he is not yet recorded + let player_rank = players_ranks_storage::read(account); + + if player_rank == 0_u128 { + // Player is not yet record, let's record + let next_player_rank = next_player_rank::read(); + players_registry::write(next_player_rank, account); + players_ranks_storage::write(account, next_player_rank); + + let next_player_rank_plus_one = next_player_rank + 1_u128; + next_player_rank::write(next_player_rank_plus_one); + + New_Player(account, next_player_rank); + } + } + + //////////////////////////////// + // Internal Functions + //////////////////////////////// + fn only_exercise_or_admin() { + let caller: ContractAddress = get_caller_address(); + let permission: bool = exercises_and_admins_accounts::read(caller); + assert (permission == true, 'You dont have permission.'); + } + + +} diff --git a/src/utils/sample_name.json b/src/utils/sample_name.json new file mode 100644 index 0000000..4a4b409 --- /dev/null +++ b/src/utils/sample_name.json @@ -0,0 +1 @@ +[1477539817190980062013511436222722368611442480 1477539817190980062013511436222722368611442481 1477539817190980062013511436222722368611442482 1477539817190980062013511436222722368611442483 1477539817190980062013511436222722368611442484 1477539817190980062013511436222722368611442485 1477539817190980062013511436222722368611442486 1477539817190980062013511436222722368611442487 1477539817190980062013511436222722368611442488 1477539817190980062013511436222722368611442489 378250193200890895875458927673016926364529275184 378250193200890895875458927673016926364529275185 378250193200890895875458927673016926364529275186 378250193200890895875458927673016926364529275187 378250193200890895875458927673016926364529275188 378250193200890895875458927673016926364529275189 378250193200890895875458927673016926364529275190 378250193200890895875458927673016926364529275191 378250193200890895875458927673016926364529275192 378250193200890895875458927673016926364529275193 378250193200890895875458927673016926364529275440 378250193200890895875458927673016926364529275441 378250193200890895875458927673016926364529275442 378250193200890895875458927673016926364529275443 378250193200890895875458927673016926364529275444 378250193200890895875458927673016926364529275445 378250193200890895875458927673016926364529275446 378250193200890895875458927673016926364529275447 378250193200890895875458927673016926364529275448 378250193200890895875458927673016926364529275449 378250193200890895875458927673016926364529275696 378250193200890895875458927673016926364529275697 378250193200890895875458927673016926364529275698 378250193200890895875458927673016926364529275699 378250193200890895875458927673016926364529275700 378250193200890895875458927673016926364529275701 378250193200890895875458927673016926364529275702 378250193200890895875458927673016926364529275703 378250193200890895875458927673016926364529275704 378250193200890895875458927673016926364529275705 378250193200890895875458927673016926364529275952 378250193200890895875458927673016926364529275953 378250193200890895875458927673016926364529275954 378250193200890895875458927673016926364529275955 378250193200890895875458927673016926364529275956 378250193200890895875458927673016926364529275957 378250193200890895875458927673016926364529275958 378250193200890895875458927673016926364529275959 378250193200890895875458927673016926364529275960 378250193200890895875458927673016926364529275961 378250193200890895875458927673016926364529276208 378250193200890895875458927673016926364529276209 378250193200890895875458927673016926364529276210 378250193200890895875458927673016926364529276211 378250193200890895875458927673016926364529276212 378250193200890895875458927673016926364529276213 378250193200890895875458927673016926364529276214 378250193200890895875458927673016926364529276215 378250193200890895875458927673016926364529276216 378250193200890895875458927673016926364529276217 378250193200890895875458927673016926364529276464 378250193200890895875458927673016926364529276465 378250193200890895875458927673016926364529276466 378250193200890895875458927673016926364529276467 378250193200890895875458927673016926364529276468 378250193200890895875458927673016926364529276469 378250193200890895875458927673016926364529276470 378250193200890895875458927673016926364529276471 378250193200890895875458927673016926364529276472 378250193200890895875458927673016926364529276473 378250193200890895875458927673016926364529276720 378250193200890895875458927673016926364529276721 378250193200890895875458927673016926364529276722 378250193200890895875458927673016926364529276723 378250193200890895875458927673016926364529276724 378250193200890895875458927673016926364529276725 378250193200890895875458927673016926364529276726 378250193200890895875458927673016926364529276727 378250193200890895875458927673016926364529276728 378250193200890895875458927673016926364529276729 378250193200890895875458927673016926364529276976 378250193200890895875458927673016926364529276977 378250193200890895875458927673016926364529276978 378250193200890895875458927673016926364529276979 378250193200890895875458927673016926364529276980 378250193200890895875458927673016926364529276981 378250193200890895875458927673016926364529276982 378250193200890895875458927673016926364529276983 378250193200890895875458927673016926364529276984 378250193200890895875458927673016926364529276985 378250193200890895875458927673016926364529277232 378250193200890895875458927673016926364529277233 378250193200890895875458927673016926364529277234 378250193200890895875458927673016926364529277235 378250193200890895875458927673016926364529277236 378250193200890895875458927673016926364529277237 378250193200890895875458927673016926364529277238 378250193200890895875458927673016926364529277239 378250193200890895875458927673016926364529277240 378250193200890895875458927673016926364529277241] \ No newline at end of file diff --git a/src/utils/sample_symbol.json b/src/utils/sample_symbol.json new file mode 100644 index 0000000..4642602 --- /dev/null +++ b/src/utils/sample_symbol.json @@ -0,0 +1 @@ +[18668896499556144 18668896499556145 18668896499556146 18668896499556147 18668896499556148 18668896499556149 18668896499556150 18668896499556151 18668896499556152 18668896499556153 4779237503886373168 4779237503886373169 4779237503886373170 4779237503886373171 4779237503886373172 4779237503886373173 4779237503886373174 4779237503886373175 4779237503886373176 4779237503886373177 4779237503886373424 4779237503886373425 4779237503886373426 4779237503886373427 4779237503886373428 4779237503886373429 4779237503886373430 4779237503886373431 4779237503886373432 4779237503886373433 4779237503886373680 4779237503886373681 4779237503886373682 4779237503886373683 4779237503886373684 4779237503886373685 4779237503886373686 4779237503886373687 4779237503886373688 4779237503886373689 4779237503886373936 4779237503886373937 4779237503886373938 4779237503886373939 4779237503886373940 4779237503886373941 4779237503886373942 4779237503886373943 4779237503886373944 4779237503886373945 4779237503886374192 4779237503886374193 4779237503886374194 4779237503886374195 4779237503886374196 4779237503886374197 4779237503886374198 4779237503886374199 4779237503886374200 4779237503886374201 4779237503886374448 4779237503886374449 4779237503886374450 4779237503886374451 4779237503886374452 4779237503886374453 4779237503886374454 4779237503886374455 4779237503886374456 4779237503886374457 4779237503886374704 4779237503886374705 4779237503886374706 4779237503886374707 4779237503886374708 4779237503886374709 4779237503886374710 4779237503886374711 4779237503886374712 4779237503886374713 4779237503886374960 4779237503886374961 4779237503886374962 4779237503886374963 4779237503886374964 4779237503886374965 4779237503886374966 4779237503886374967 4779237503886374968 4779237503886374969 4779237503886375216 4779237503886375217 4779237503886375218 4779237503886375219 4779237503886375220 4779237503886375221 4779237503886375222 4779237503886375223 4779237503886375224 4779237503886375225] \ No newline at end of file From 6b5703d43ec028d316396fc01a56e9b548c3d9c3 Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 30 May 2023 09:51:24 +0200 Subject: [PATCH 02/11] -updated to cairo v1.1.0 and scarb v0.3 -fixed the bool_eq issue --- .vscode/settings.json | 3 + Scarb.toml | 4 +- src/ERC721/ERC721.cairo | 164 +++++++++++++++++++++++++++++++ src/evaluator.cairo | 8 +- src/token/ERC20_base.cairo | 2 +- src/token/TDERC20.cairo | 5 +- src/utils/ex00_base.cairo | 7 +- src/utils/helper.cairo | 10 ++ src/utils/players_registry.cairo | 7 +- 9 files changed, 197 insertions(+), 13 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/ERC721/ERC721.cairo diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6b665aa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} diff --git a/Scarb.toml b/Scarb.toml index 4978f43..344521a 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,8 +1,10 @@ [package] name = "starknet_erc721" -version = "0.1.0" +version = "0.3.0" description = "Workshop to learn the basics of ERC721." homepage = "https://github.com/starknet-edu/starknet-erc721" +[dependencies] +starknet = ">=1.0.0" [[target.starknet-contract]] diff --git a/src/ERC721/ERC721.cairo b/src/ERC721/ERC721.cairo new file mode 100644 index 0000000..5b19ef0 --- /dev/null +++ b/src/ERC721/ERC721.cairo @@ -0,0 +1,164 @@ +//////////////////////////////// +// ERC721Base +// A Base ERC721 contract to implement ERC721 standarded methods +// such as `transfer`, `transfer_from`, `mint`, 'burn', etc. +//////////////////////////////// + +#[contract] +#[derive(Copy, Drop)] +mod ERC721Base { + use zeroable::Zeroable; + use starknet::get_caller_address; + use starknet::ContractAddress; + use starknet::contract_address_const; + use starknet::ContractAddressZeroable; + use starknet::Felt252TryIntoContractAddress; + use starknet::ContractAddressIntoFelt252; + use traits::TryInto; + use traits::Into; + use option::OptionTrait; + + //////////////////////////////// + // Struct + //////////////////////////////// + + struct Storage { + name: felt252, + symbol: felt252, + owners: LegacyMap::, + balances: LegacyMap::, + token_approvals: LegacyMap::, + operator_approvals: LegacyMap::<(ContractAddress, ContractAddress), bool>, + } + + //////////////////////////////// + // View Functions + //////////////////////////////// + + fn get_name() -> felt252 { + name::read() + } + + fn get_symbol() -> felt252 { + symbol::read() + } + + fn owner_of(token_id: u256) -> ContractAddress { + let owner = owners::read(token_id); + assert(!owner.is_zero(), 'ERC721: invalid token ID'); + owner + } + + fn balance_of(account: ContractAddress) -> u256 { + assert(!account.is_zero(), 'ERC721: address zero'); + balances::read(account) + } + + fn get_approved(token_id: u256) -> ContractAddress { + assert(_exists(token_id), 'ERC721: invalid token ID'); + token_approvals::read(token_id) + } + + fn is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool { + operator_approvals::read((owner, operator)) + } + + //////////////////////////////// + // Internal Constructor + //////////////////////////////// + fn initializer( + name_: felt252, symbol_: felt252 + ) { + name::write(name_); + symbol::write(symbol_); + } + + //////////////////////////////// + // Internal FUNCTIONS + //////////////////////////////// + + fn approve(to: ContractAddress, token_id: u256) { + let owner = _owner_of(token_id); + + assert(to.into() != owner.into(), 'Approval to current owner'); + + assert(get_caller_address().into() == owner.into() | is_approved_for_all(owner, get_caller_address()), 'Not token owner'); + _approve(to, token_id); + } + + fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256) { + assert(_is_approved_or_owner(from, token_id), 'Caller is not owner or approved'); + _transfer(from, to, token_id); + } + + fn set_approval_for_all(operator: ContractAddress, approved: bool) { + let caller = get_caller_address(); + assert(!caller.is_zero() & !operator.is_zero(), 'ERC721: Caller/Operator is zero'); + + assert(caller.into() != operator.into(), 'ERC721: approve to caller'); + operator_approvals::write((caller, operator), approved); + // ApprovalForAll(caller, operator, approved); + } + + fn _mint(to: ContractAddress, token_id: u256) { + assert(!to.is_zero(), 'ERC721: mint to 0'); + assert(!_exists(token_id), 'ERC721: already minted'); + + balances::write(to, balances::read(to) + 1.into()); + owners::write(token_id, to); + + // Transfer(contract_address_const::<0>(), to, token_id); + + } + + fn _burn(token_id: u256) { + + let owner = owner_of(token_id); + + token_approvals::write(token_id, contract_address_const::<0>()); + + balances::write(owner, balances::read(owner) - 1.into()); + owners::write(token_id, contract_address_const::<0>()); + + // Transfer(owner, contract_address_const::<0>(), token_id); + } + + fn _transfer(from: ContractAddress, to: ContractAddress, token_id: u256) { + assert(from.into() == owner_of(token_id).into(), 'Transfer from incorrect owner'); + assert(!to.is_zero(), 'ERC721: transfer to 0'); + + token_approvals::write(token_id, contract_address_const::<0>()); + + balances::write(from, balances::read(from) - 1.into()); + balances::write(to, balances::read(to) + 1.into()); + + owners::write(token_id, to); + + // Transfer(from, to, token_id); + + } + + fn _approve(to: ContractAddress, token_id: u256) { + token_approvals::write(token_id, to); + // Approval(owner_of(token_id), to, token_id); + } + + fn _is_approved_or_owner(spender: ContractAddress, token_id: u256) -> bool { + let owner = owners::read(token_id); + + spender.into() == owner.into() + | is_approved_for_all(owner, spender) + | get_approved(token_id).into() == spender.into() + } + + fn _exists(token_id: u256) -> bool { + !_owner_of(token_id).is_zero() + } + + fn _owner_of(token_id: u256) -> ContractAddress { + owners::read(token_id) + } + + + +} diff --git a/src/evaluator.cairo b/src/evaluator.cairo index 5ecd560..3de67ab 100644 --- a/src/evaluator.cairo +++ b/src/evaluator.cairo @@ -29,6 +29,7 @@ mod Evaluator{ use starknet_erc721::utils::ex00_base::Ex00Base::ex_initializer; use starknet_erc721::utils::ex00_base::Ex00Base::update_class_hash_by_admin; use starknet_erc721::utils::helper; + use starknet_erc721::utils::helper::check_boolean; use starknet_erc721::ERC721::IERC721::IERC721Dispatcher; use starknet_erc721::ERC721::IERC721::IERC721DispatcherTrait; @@ -218,7 +219,7 @@ mod Evaluator{ let sender_address = get_caller_address(); // Check if exercise has been submited before. - assert(has_been_paired::read(exercise_address) != true, 'SOLUTION_SUBMITED_ALREADY'); + assert(check_boolean(has_been_paired::read(exercise_address)) != check_boolean(true), 'SOLUTION_SUBMITED_ALREADY'); // Store exercise address player_exercise_solution_storage::write(sender_address, exercise_address); @@ -251,11 +252,12 @@ mod Evaluator{ fn update_class_hash(class_hash: felt252) { update_class_hash_by_admin(class_hash); } + #[external] fn set_random_names(values: Array::) { // Check if the random values were already initialized let was_initialized_read = was_initialized::read(0_u8); - assert(was_initialized_read != true, 'NOT_INITIALISED'); + assert(check_boolean(was_initialized_read) != check_boolean(true), 'NOT_INITIALISED'); let mut idx: u128 = 0_u128; set_a_random_name(idx, values); @@ -268,7 +270,7 @@ mod Evaluator{ fn set_random_symbols(values: Array::) { // Check if the random values were already initialized let was_initialized_read = was_initialized::read(1_u8); - assert(was_initialized_read != true, 'NOT_INITIALISED'); + assert(check_boolean(was_initialized_read) != check_boolean(true), 'NOT_INITIALISED'); let mut idx: u128 = 0_u128; set_a_random_symbol(idx, values); diff --git a/src/token/ERC20_base.cairo b/src/token/ERC20_base.cairo index 8978c89..30cef4b 100644 --- a/src/token/ERC20_base.cairo +++ b/src/token/ERC20_base.cairo @@ -11,7 +11,7 @@ mod ERC20Base { use zeroable::Zeroable; use starknet::contract_address_const; use starknet::ContractAddress; - use starknet::ContractAddressZeroable; + use starknet::contract_address::ContractAddressZeroable; use traits::Into; use traits::TryInto; use array::ArrayTrait; diff --git a/src/token/TDERC20.cairo b/src/token/TDERC20.cairo index 32709f5..281b112 100644 --- a/src/token/TDERC20.cairo +++ b/src/token/TDERC20.cairo @@ -36,6 +36,7 @@ mod TDERC20 { use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transfer; use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transferFrom; use starknet_erc721::utils::helper; + use starknet_erc721::utils::helper::check_boolean; struct Storage { is_transferable_storage: bool, @@ -190,12 +191,12 @@ mod TDERC20 { fn only_teacher_or_exercise() { let caller = get_caller_address(); let permission = teachers_and_exercises_accounts::read(caller); - assert(permission == true, 'NO_PERMISSION'); + assert(check_boolean(permission) == check_boolean(true), 'NO_PERMISSION'); } fn _is_transferable() { let permission = is_transferable_storage::read(); - assert(permission == true, 'NOT_TRANSFERABLE'); + assert(check_boolean(permission) == check_boolean(true), 'NOT_TRANSFERABLE'); } #[external] fn update_class_hash_by_admin(class_hash_in_felt: felt252) { diff --git a/src/utils/ex00_base.cairo b/src/utils/ex00_base.cairo index 0f2dc2e..873fd7d 100644 --- a/src/utils/ex00_base.cairo +++ b/src/utils/ex00_base.cairo @@ -11,7 +11,7 @@ mod Ex00Base { use starknet::get_caller_address; use zeroable::Zeroable; use starknet::ContractAddress; - use starknet::ContractAddressZeroable; + use starknet::contract_address::ContractAddressZeroable; use starknet::syscalls::replace_class_syscall; use starknet::ClassHash; use starknet::class_hash::Felt252TryIntoClassHash; @@ -26,6 +26,7 @@ mod Ex00Base { use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcher; use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; + use starknet_erc721::utils::helper::check_boolean; const Decimals: u128 = 1000000000000000000_u128; @@ -108,7 +109,7 @@ mod Ex00Base { Iplayers_registryDispatcher{contract_address: players_registry} .has_validated_exercise(account, workshop_id, exercise_id); - assert(has_current_user_validated_exercise == false, 'Exercise previously validated'); + assert(check_boolean(has_current_user_validated_exercise) == check_boolean(false), 'Exercise previously validated'); Iplayers_registryDispatcher{contract_address: players_registry} .validate_exercise(account, workshop_id, exercise_id); } @@ -120,7 +121,7 @@ mod Ex00Base { let is_admin = Iplayers_registryDispatcher{contract_address: players_registry} .is_exercise_or_admin(sender_address); - assert (is_admin == true, 'CALLER_NO_ADMIN_RIGHTS'); + assert (check_boolean(is_admin) == check_boolean(true), 'CALLER_NO_ADMIN_RIGHTS'); let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); replace_class_syscall(class_hash); } diff --git a/src/utils/helper.cairo b/src/utils/helper.cairo index 188c862..dc9d615 100644 --- a/src/utils/helper.cairo +++ b/src/utils/helper.cairo @@ -34,3 +34,13 @@ fn get_token_in_decimals(decimals: u8) -> u128 { DECIMALS_6 } } + +// Checking boolean assertions +#[inline(always)] +fn check_boolean(value: bool) -> u8 { + if value { + 1_u8 + } else { + 0_u8 + } +} diff --git a/src/utils/players_registry.cairo b/src/utils/players_registry.cairo index 1c0f09d..7218759 100644 --- a/src/utils/players_registry.cairo +++ b/src/utils/players_registry.cairo @@ -10,7 +10,7 @@ mod PlayersRegistry { use starknet::get_caller_address; use zeroable::Zeroable; use starknet::ContractAddress; - use starknet::ContractAddressZeroable; + use starknet::contract_address::ContractAddressZeroable; use traits::Into; use traits::TryInto; use array::ArrayTrait; @@ -26,6 +26,7 @@ mod PlayersRegistry { use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; use starknet_erc721::utils::helper; + use starknet_erc721::utils::helper::check_boolean; //////////////////////////////// // STORAGE @@ -125,7 +126,7 @@ mod PlayersRegistry { (account, workshop, exercise) ); - assert(is_validated == false, 'USER_VALIDATED'); + assert(check_boolean(is_validated) == check_boolean(false), 'USER_VALIDATED'); // Marking the exercise as completed has_validated_exercise_storage::write((account, workshop, exercise), true); @@ -153,7 +154,7 @@ mod PlayersRegistry { fn only_exercise_or_admin() { let caller: ContractAddress = get_caller_address(); let permission: bool = exercises_and_admins_accounts::read(caller); - assert (permission == true, 'You dont have permission.'); + assert (check_boolean(permission) == check_boolean(true), 'You dont have permission.'); } From d0e33377920289babc661058d32a4f44bf97f21a Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 30 May 2023 10:15:56 +0200 Subject: [PATCH 03/11] - updated the evaluator with 2 more exercises - approve() and set_aprove_for_all() --- src/ERC721/IERC721.cairo | 3 ++ src/evaluator.cairo | 67 ++++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/ERC721/IERC721.cairo b/src/ERC721/IERC721.cairo index aa63894..208494c 100644 --- a/src/ERC721/IERC721.cairo +++ b/src/ERC721/IERC721.cairo @@ -10,9 +10,12 @@ trait IERC721 { fn get_symbol() -> felt252; fn owner_of(token_id: u256) -> ContractAddress; fn balance_of(account: ContractAddress) -> u256; + fn get_approved(token_id: u256) -> ContractAddress; + fn is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool; fn mint(to: ContractAddress, token_id: u256); fn burn(token_id: u256); fn approve(to: ContractAddress, token_id: u256); + fn set_approval_for_all(operator: ContractAddress, approved: bool); fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256); } diff --git a/src/evaluator.cairo b/src/evaluator.cairo index 3de67ab..07343b2 100644 --- a/src/evaluator.cairo +++ b/src/evaluator.cairo @@ -127,16 +127,16 @@ mod Evaluator{ let sender_address = get_caller_address(); // Retrieve the evaluator address - let contract_address = get_contract_address(); + let _contract_address = get_contract_address(); // minting token_id - IERC721Dispatcher{contract_address: submitted_exercise_address}.mint(contract_address, token_id); + IERC721Dispatcher{contract_address: submitted_exercise_address}.mint(_contract_address, token_id); // Retrieve the owner of token_id let check_owner_of = IERC721Dispatcher{contract_address: submitted_exercise_address}.owner_of(token_id); // Checking if owner of the token_id is the evaluator - assert(check_owner_of == contract_address, 'NOT_THE_OWNER'); + assert(check_owner_of == _contract_address, 'NOT_THE_OWNER'); // Checking if the user has validated the exercise before validate_exercise(sender_address); @@ -154,16 +154,16 @@ mod Evaluator{ let sender_address = get_caller_address(); // Get the evaluator address - let contract_address = get_contract_address(); + let _contract_address = get_contract_address(); // Retrieve balance before burn - let balance_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(contract_address); + let balance_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(_contract_address); // check if burn method works IERC721Dispatcher{contract_address: submitted_exercise_address}.burn(token_id); // Retrieve balance after burn - let balance_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(contract_address); + let balance_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(_contract_address); // Checking if owner of the token_id is the evaluator assert(balance_c2 == balance_c1 - u256_from_felt252(1), 'BALANCE_INCORRECT'); @@ -176,7 +176,56 @@ mod Evaluator{ } #[external] - fn ex_04_erc721_transfer(token_id: u256){ + fn ex_04_erc721_approve(token_id: u256){ + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // call the approve function + IERC721Dispatcher{contract_address: submitted_exercise_address}.approve(sender_address, token_id); + + // retrieving result + let approved_address = IERC721Dispatcher{contract_address: submitted_exercise_address}.get_approved(token_id); + + // checking if approve function is correctly executed + assert(approved_address == sender_address, 'ADDRESS_NOT_APPROVED'); + + // 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] + fn ex_05_erc721_approve_for_all(){ + // Run the verification steps before continuing + let submitted_exercise_address:ContractAddress = verify(); + + // Retrieve caller address + let sender_address = get_caller_address(); + + // Get the evaluator address + let _contract_address = get_contract_address(); + + // call the approve for all function + IERC721Dispatcher{contract_address: submitted_exercise_address}.set_approval_for_all(sender_address, true); + + // retrieving result + let is_approved = IERC721Dispatcher{contract_address: submitted_exercise_address}.is_approved_for_all(_contract_address, sender_address); + + assert(check_boolean(is_approved) == check_boolean(true), 'NOT_APPROVED_FOR_ALL'); + + // 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] + fn ex_06_erc721_transfer(token_id: u256){ // Run the verification steps before continuing let submitted_exercise_address:ContractAddress = verify(); @@ -185,7 +234,7 @@ mod Evaluator{ let sender_address = get_caller_address(); // Get the evaluator address - let contract_address = get_contract_address(); + let _contract_address = get_contract_address(); // Retrieve balance and owner before transfer let balance_c1 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(sender_address); @@ -195,7 +244,7 @@ mod Evaluator{ IERC721Dispatcher{contract_address: submitted_exercise_address}.approve(sender_address, token_id); // approve for transfer - IERC721Dispatcher{contract_address: submitted_exercise_address}.transfer_from(contract_address, sender_address, token_id); + IERC721Dispatcher{contract_address: submitted_exercise_address}.transfer_from(_contract_address, sender_address, token_id); // Retrieve balance and owner after transfer let balance_c2 = IERC721Dispatcher{contract_address: submitted_exercise_address}.balance_of(sender_address); From 800543581024b227e930f63f6d68ae96e2088f71 Mon Sep 17 00:00:00 2001 From: robertkodra Date: Mon, 5 Jun 2023 15:09:35 +0200 Subject: [PATCH 04/11] update with deployed evaluator and small fixes --- src/ERC721/ERC721.cairo | 164 ------------------------------- src/README.md | 22 ++++- src/deploy_doc.md | 93 ++++++++++++++++++ src/evaluator.cairo | 21 ++-- src/temp.md | 33 ------- src/token/TDERC20.cairo | 5 +- src/utils/ex00_base.cairo | 9 +- src/utils/helper.py | 4 +- src/utils/players_registry.cairo | 5 +- src/utils/sample_name.json | 2 +- src/utils/sample_symbol.json | 2 +- 11 files changed, 134 insertions(+), 226 deletions(-) delete mode 100644 src/ERC721/ERC721.cairo create mode 100644 src/deploy_doc.md delete mode 100644 src/temp.md diff --git a/src/ERC721/ERC721.cairo b/src/ERC721/ERC721.cairo deleted file mode 100644 index 5b19ef0..0000000 --- a/src/ERC721/ERC721.cairo +++ /dev/null @@ -1,164 +0,0 @@ -//////////////////////////////// -// ERC721Base -// A Base ERC721 contract to implement ERC721 standarded methods -// such as `transfer`, `transfer_from`, `mint`, 'burn', etc. -//////////////////////////////// - -#[contract] -#[derive(Copy, Drop)] -mod ERC721Base { - use zeroable::Zeroable; - use starknet::get_caller_address; - use starknet::ContractAddress; - use starknet::contract_address_const; - use starknet::ContractAddressZeroable; - use starknet::Felt252TryIntoContractAddress; - use starknet::ContractAddressIntoFelt252; - use traits::TryInto; - use traits::Into; - use option::OptionTrait; - - //////////////////////////////// - // Struct - //////////////////////////////// - - struct Storage { - name: felt252, - symbol: felt252, - owners: LegacyMap::, - balances: LegacyMap::, - token_approvals: LegacyMap::, - operator_approvals: LegacyMap::<(ContractAddress, ContractAddress), bool>, - } - - //////////////////////////////// - // View Functions - //////////////////////////////// - - fn get_name() -> felt252 { - name::read() - } - - fn get_symbol() -> felt252 { - symbol::read() - } - - fn owner_of(token_id: u256) -> ContractAddress { - let owner = owners::read(token_id); - assert(!owner.is_zero(), 'ERC721: invalid token ID'); - owner - } - - fn balance_of(account: ContractAddress) -> u256 { - assert(!account.is_zero(), 'ERC721: address zero'); - balances::read(account) - } - - fn get_approved(token_id: u256) -> ContractAddress { - assert(_exists(token_id), 'ERC721: invalid token ID'); - token_approvals::read(token_id) - } - - fn is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool { - operator_approvals::read((owner, operator)) - } - - //////////////////////////////// - // Internal Constructor - //////////////////////////////// - fn initializer( - name_: felt252, symbol_: felt252 - ) { - name::write(name_); - symbol::write(symbol_); - } - - //////////////////////////////// - // Internal FUNCTIONS - //////////////////////////////// - - fn approve(to: ContractAddress, token_id: u256) { - let owner = _owner_of(token_id); - - assert(to.into() != owner.into(), 'Approval to current owner'); - - assert(get_caller_address().into() == owner.into() | is_approved_for_all(owner, get_caller_address()), 'Not token owner'); - _approve(to, token_id); - } - - fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256) { - assert(_is_approved_or_owner(from, token_id), 'Caller is not owner or approved'); - _transfer(from, to, token_id); - } - - fn set_approval_for_all(operator: ContractAddress, approved: bool) { - let caller = get_caller_address(); - assert(!caller.is_zero() & !operator.is_zero(), 'ERC721: Caller/Operator is zero'); - - assert(caller.into() != operator.into(), 'ERC721: approve to caller'); - operator_approvals::write((caller, operator), approved); - // ApprovalForAll(caller, operator, approved); - } - - fn _mint(to: ContractAddress, token_id: u256) { - assert(!to.is_zero(), 'ERC721: mint to 0'); - assert(!_exists(token_id), 'ERC721: already minted'); - - balances::write(to, balances::read(to) + 1.into()); - owners::write(token_id, to); - - // Transfer(contract_address_const::<0>(), to, token_id); - - } - - fn _burn(token_id: u256) { - - let owner = owner_of(token_id); - - token_approvals::write(token_id, contract_address_const::<0>()); - - balances::write(owner, balances::read(owner) - 1.into()); - owners::write(token_id, contract_address_const::<0>()); - - // Transfer(owner, contract_address_const::<0>(), token_id); - } - - fn _transfer(from: ContractAddress, to: ContractAddress, token_id: u256) { - assert(from.into() == owner_of(token_id).into(), 'Transfer from incorrect owner'); - assert(!to.is_zero(), 'ERC721: transfer to 0'); - - token_approvals::write(token_id, contract_address_const::<0>()); - - balances::write(from, balances::read(from) - 1.into()); - balances::write(to, balances::read(to) + 1.into()); - - owners::write(token_id, to); - - // Transfer(from, to, token_id); - - } - - fn _approve(to: ContractAddress, token_id: u256) { - token_approvals::write(token_id, to); - // Approval(owner_of(token_id), to, token_id); - } - - fn _is_approved_or_owner(spender: ContractAddress, token_id: u256) -> bool { - let owner = owners::read(token_id); - - spender.into() == owner.into() - | is_approved_for_all(owner, spender) - | get_approved(token_id).into() == spender.into() - } - - fn _exists(token_id: u256) -> bool { - !_owner_of(token_id).is_zero() - } - - fn _owner_of(token_id: u256) -> ContractAddress { - owners::read(token_id) - } - - - -} diff --git a/src/README.md b/src/README.md index 02d4ef1..02a3fe5 100644 --- a/src/README.md +++ b/src/README.md @@ -41,14 +41,30 @@ Here, we will focus on creating the burn function. 1. Create the `burn()` function that allows you to burn an NFT. 2. Deploy your contract on testnet 3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -4. Send a token to the Evaluator contract or use the previous exercise to mint a new token. +4. Send a token to the Evaluator contract by using the mint function from your deployed function. 5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. -### Exercise 4 - Transfering a token +### Exercise 4 - Approve function + +1. Create the `approve()` function +2. Create the `get_approved()` function for the Evaluator to receive the results back +3. Deploy your contract on testnet +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_04_erc721_approve()` to verify your contract and receive points. + +### Exercise 5 - Approve all function + +1. Create the `set_approval_for_all()` function +2. Create the `is_approved_for_all()` function for the Evaluator to receive the results back +3. Deploy your contract on testnet +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_05_erc721_approve_for_all()` to verify your contract and receive points. + +### Exercise 6 - Transfering a token Here, we will focus on creating the transfer function. 1. Create the `transfer_from()` function that allows you to transfer the NFT. 2. Deploy your contract on testnet 3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -4. Call `ex_04_erc721_transfer()` to verify your contract and receive points. +4. Call `ex_06_erc721_transfer()` to verify your contract and receive points. diff --git a/src/deploy_doc.md b/src/deploy_doc.md new file mode 100644 index 0000000..591f8a6 --- /dev/null +++ b/src/deploy_doc.md @@ -0,0 +1,93 @@ +# Cheatsheet + +## Deploying Exercise: + +| Contract | Class hash | Deployed contract | Permission | +| --------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ---------- | +| Evaluator | 0x34b3e7e68ecc8d101d97941005d69d5c868c39dcaa3dca50e402162e4a49e63 | 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 | TBA | +| Player Registry | 0x53eb2d57dbc61faec5df58bd5c872c6d42bb27a6c0e434caa33091919ab61a1 | 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf | TBA | +| TDERC20 | 0x07c75b9f9e69b7126aa71dbc14d81eede1145fc175a7ee19e7c8c77a25e6c2b0 | 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 | TBA | +| --------- | ---------- | ----------------- | ---------- | +| Evaluator | TBA | TBA | TBA | + +## Useful comands: + +Deploying players registry and ERC20 and checking admin is registered + +### Deploying Player Registry + +```bash +# Players registry +starknet declare --contract target/dev/starknet_erc721_PlayersRegistry.sierra.json --account version_2 +/// +starknet deploy --class_hash 0x7ee78436214b95bae10b988e9a6edf1c8f9c572cf68c4e2350d9d76194eb4c1 --account version_2 --inputs 0x018E41c9c91ea1EaB61438Ab3dcB93EB2dD4f80072dD0e5F0f7B22eaAbd70dAc +``` + +### Deploying TDERC20 + +```bash +# Declare TDERC20 +starknet declare --contract target/dev/starknet_erc721_TDERC20.sierra.json --account version_2 + +# Deploy TDERC20 +starknet deploy --class_hash 0x79fe8e1cadfb3a194eabbbd9465388dbdb8cd0a21034bf56c8a1e776163f648 --account version_2 --inputs 0x434149524f312d455243373231 0x434149524f312d455243373231 18 0 0 0x018E41c9c91ea1EaB61438Ab3dcB93EB2dD4f80072dD0e5F0f7B22eaAbd70dAc 0x018E41c9c91ea1EaB61438Ab3dcB93EB2dD4f80072dD0e5F0f7B22eaAbd70dAc +``` + +### Verification: + +Checking if the admin has been set correctly. Returns `1` if `true` +. + +```bash +############### +# Player Registry +starknet call --function is_exercise_or_admin --address 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf --inputs 0x018E41c9c91ea1EaB61438Ab3dcB93EB2dD4f80072dD0e5F0f7B22eaAbd70dAc + +# ERC20 +starknet call --function is_teacher_or_exercise --address 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 --inputs 0x018E41c9c91ea1EaB61438Ab3dcB93EB2dD4f80072dD0e5F0f7B22eaAbd70dAc +``` + +### Declaring Evaluator: + +```bash +# Declare Evaluator +starknet declare --contract target/dev/starknet_erc721_Evaluator.sierra.json --account version_2 + +# Deploy Evaluator +starknet deploy --class_hash 0x218c1a0814470c5571608284c1f6d9467f6baeb3f11d41e7b3b22f807e050ef --account version_2 --inputs 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf 1 1 +``` + +### Adding exercise as admin in TDERC20 and Player Registry + +```bash +#TDERC20 +starknet invoke --function set_teachers --address 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 --account version_2 --inputs 1 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 1 1 + +# Player Registry +starknet invoke --function set_teachers --address 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf --account version_2 --inputs 1 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 1 1 +``` + +### Check if Evaluator has been added: + +```bash +############### +# Player Registry +starknet call --function is_exercise_or_admin --address 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf --inputs 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 + +# ERC20 +starknet call --function is_teacher_or_exercise --address 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 --inputs 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 +``` + +### Setting up random variables + +Setting random names: + +```bash +starknet invoke --function set_random_names --address 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 --account version_2 --max_fee 10000000000000000 --input 100 92143863346085372133985850962073309232 92143863346085372133985850962073309233 92143863346085372133985850962073309234 92143863346085372133985850962073309235 92143863346085372133985850962073309236 92143863346085372133985850962073309237 92143863346085372133985850962073309238 92143863346085372133985850962073309239 92143863346085372133985850962073309240 92143863346085372133985850962073309241 23588829016597855266300377846290767163696 23588829016597855266300377846290767163697 23588829016597855266300377846290767163698 23588829016597855266300377846290767163699 23588829016597855266300377846290767163700 23588829016597855266300377846290767163701 23588829016597855266300377846290767163702 23588829016597855266300377846290767163703 23588829016597855266300377846290767163704 23588829016597855266300377846290767163705 23588829016597855266300377846290767163952 23588829016597855266300377846290767163953 23588829016597855266300377846290767163954 23588829016597855266300377846290767163955 23588829016597855266300377846290767163956 23588829016597855266300377846290767163957 23588829016597855266300377846290767163958 23588829016597855266300377846290767163959 23588829016597855266300377846290767163960 23588829016597855266300377846290767163961 23588829016597855266300377846290767164208 23588829016597855266300377846290767164209 23588829016597855266300377846290767164210 23588829016597855266300377846290767164211 23588829016597855266300377846290767164212 23588829016597855266300377846290767164213 23588829016597855266300377846290767164214 23588829016597855266300377846290767164215 23588829016597855266300377846290767164216 23588829016597855266300377846290767164217 23588829016597855266300377846290767164464 23588829016597855266300377846290767164465 23588829016597855266300377846290767164466 23588829016597855266300377846290767164467 23588829016597855266300377846290767164468 23588829016597855266300377846290767164469 23588829016597855266300377846290767164470 23588829016597855266300377846290767164471 23588829016597855266300377846290767164472 23588829016597855266300377846290767164473 23588829016597855266300377846290767164720 23588829016597855266300377846290767164721 23588829016597855266300377846290767164722 23588829016597855266300377846290767164723 23588829016597855266300377846290767164724 23588829016597855266300377846290767164725 23588829016597855266300377846290767164726 23588829016597855266300377846290767164727 23588829016597855266300377846290767164728 23588829016597855266300377846290767164729 23588829016597855266300377846290767164976 23588829016597855266300377846290767164977 23588829016597855266300377846290767164978 23588829016597855266300377846290767164979 23588829016597855266300377846290767164980 23588829016597855266300377846290767164981 23588829016597855266300377846290767164982 23588829016597855266300377846290767164983 23588829016597855266300377846290767164984 23588829016597855266300377846290767164985 23588829016597855266300377846290767165232 23588829016597855266300377846290767165233 23588829016597855266300377846290767165234 23588829016597855266300377846290767165235 23588829016597855266300377846290767165236 23588829016597855266300377846290767165237 23588829016597855266300377846290767165238 23588829016597855266300377846290767165239 23588829016597855266300377846290767165240 23588829016597855266300377846290767165241 23588829016597855266300377846290767165488 23588829016597855266300377846290767165489 23588829016597855266300377846290767165490 23588829016597855266300377846290767165491 23588829016597855266300377846290767165492 23588829016597855266300377846290767165493 23588829016597855266300377846290767165494 23588829016597855266300377846290767165495 23588829016597855266300377846290767165496 23588829016597855266300377846290767165497 23588829016597855266300377846290767165744 23588829016597855266300377846290767165745 23588829016597855266300377846290767165746 23588829016597855266300377846290767165747 23588829016597855266300377846290767165748 23588829016597855266300377846290767165749 23588829016597855266300377846290767165750 23588829016597855266300377846290767165751 23588829016597855266300377846290767165752 23588829016597855266300377846290767165753 +``` + +Setting random symbols: + +```bash +starknet invoke --function set_random_symbols --address 0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155 --account version_2 --max_fee 10000000000000000 --input 100 1278752983309224468272 1278752983309224468273 1278752983309224468274 1278752983309224468275 1278752983309224468276 1278752983309224468277 1278752983309224468278 1278752983309224468279 1278752983309224468280 1278752983309224468281 327360763727161463877936 327360763727161463877937 327360763727161463877938 327360763727161463877939 327360763727161463877940 327360763727161463877941 327360763727161463877942 327360763727161463877943 327360763727161463877944 327360763727161463877945 327360763727161463878192 327360763727161463878193 327360763727161463878194 327360763727161463878195 327360763727161463878196 327360763727161463878197 327360763727161463878198 327360763727161463878199 327360763727161463878200 327360763727161463878201 327360763727161463878448 327360763727161463878449 327360763727161463878450 327360763727161463878451 327360763727161463878452 327360763727161463878453 327360763727161463878454 327360763727161463878455 327360763727161463878456 327360763727161463878457 327360763727161463878704 327360763727161463878705 327360763727161463878706 327360763727161463878707 327360763727161463878708 327360763727161463878709 327360763727161463878710 327360763727161463878711 327360763727161463878712 327360763727161463878713 327360763727161463878960 327360763727161463878961 327360763727161463878962 327360763727161463878963 327360763727161463878964 327360763727161463878965 327360763727161463878966 327360763727161463878967 327360763727161463878968 327360763727161463878969 327360763727161463879216 327360763727161463879217 327360763727161463879218 327360763727161463879219 327360763727161463879220 327360763727161463879221 327360763727161463879222 327360763727161463879223 327360763727161463879224 327360763727161463879225 327360763727161463879472 327360763727161463879473 327360763727161463879474 327360763727161463879475 327360763727161463879476 327360763727161463879477 327360763727161463879478 327360763727161463879479 327360763727161463879480 327360763727161463879481 327360763727161463879728 327360763727161463879729 327360763727161463879730 327360763727161463879731 327360763727161463879732 327360763727161463879733 327360763727161463879734 327360763727161463879735 327360763727161463879736 327360763727161463879737 327360763727161463879984 327360763727161463879985 327360763727161463879986 327360763727161463879987 327360763727161463879988 327360763727161463879989 327360763727161463879990 327360763727161463879991 327360763727161463879992 327360763727161463879993 +``` diff --git a/src/evaluator.cairo b/src/evaluator.cairo index 07343b2..4c2d6c2 100644 --- a/src/evaluator.cairo +++ b/src/evaluator.cairo @@ -29,7 +29,6 @@ mod Evaluator{ use starknet_erc721::utils::ex00_base::Ex00Base::ex_initializer; use starknet_erc721::utils::ex00_base::Ex00Base::update_class_hash_by_admin; use starknet_erc721::utils::helper; - use starknet_erc721::utils::helper::check_boolean; use starknet_erc721::ERC721::IERC721::IERC721Dispatcher; use starknet_erc721::ERC721::IERC721::IERC721DispatcherTrait; @@ -113,7 +112,7 @@ mod Evaluator{ assert(symbol == assigned_symbol, 'SYMBOL_INCORRECT'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 1_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); } @@ -139,7 +138,7 @@ mod Evaluator{ assert(check_owner_of == _contract_address, 'NOT_THE_OWNER'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 2_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); } @@ -169,7 +168,7 @@ mod Evaluator{ assert(balance_c2 == balance_c1 - u256_from_felt252(1), 'BALANCE_INCORRECT'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 3_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); @@ -193,7 +192,7 @@ mod Evaluator{ assert(approved_address == sender_address, 'ADDRESS_NOT_APPROVED'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 4_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); @@ -216,10 +215,10 @@ mod Evaluator{ // retrieving result let is_approved = IERC721Dispatcher{contract_address: submitted_exercise_address}.is_approved_for_all(_contract_address, sender_address); - assert(check_boolean(is_approved) == check_boolean(true), 'NOT_APPROVED_FOR_ALL'); + assert(is_approved, 'NOT_APPROVED_FOR_ALL'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 5_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); } @@ -256,7 +255,7 @@ mod Evaluator{ assert(owner_c2 == sender_address, 'OWNER_WRONG'); // Checking if the user has validated the exercise before - validate_exercise(sender_address); + validate_exercise(sender_address, 6_u128); // Sending points to the address specified as parameter distribute_points(sender_address, 2_u128); @@ -268,7 +267,7 @@ mod Evaluator{ let sender_address = get_caller_address(); // Check if exercise has been submited before. - assert(check_boolean(has_been_paired::read(exercise_address)) != check_boolean(true), 'SOLUTION_SUBMITED_ALREADY'); + assert(!has_been_paired::read(exercise_address), 'SOLUTION_ALREADY_SUBMITED'); // Store exercise address player_exercise_solution_storage::write(sender_address, exercise_address); @@ -306,7 +305,7 @@ mod Evaluator{ fn set_random_names(values: Array::) { // Check if the random values were already initialized let was_initialized_read = was_initialized::read(0_u8); - assert(check_boolean(was_initialized_read) != check_boolean(true), 'NOT_INITIALISED'); + assert(!was_initialized_read, 'NAMES_INITIALISED'); let mut idx: u128 = 0_u128; set_a_random_name(idx, values); @@ -319,7 +318,7 @@ mod Evaluator{ fn set_random_symbols(values: Array::) { // Check if the random values were already initialized let was_initialized_read = was_initialized::read(1_u8); - assert(check_boolean(was_initialized_read) != check_boolean(true), 'NOT_INITIALISED'); + assert(!was_initialized_read, 'SYMBOLS_INITIALISED'); let mut idx: u128 = 0_u128; set_a_random_symbol(idx, values); diff --git a/src/temp.md b/src/temp.md deleted file mode 100644 index 4003932..0000000 --- a/src/temp.md +++ /dev/null @@ -1,33 +0,0 @@ -# Cheatsheet - -## Deploying Exercise: - -| Contract | Class hash | Deployed contract | Permission | -| --------- | ---------- | ----------------- | ---------- | -| Evaluator | TBA | TBA | TBA | - -## Useful comands: - -Deploying players registry and ERC20 and checking admin is registered - -``` -# Players registry -TBA -``` - -### Declaring Evaluator - -### Setting up random variables - -Setting random names: - -``` -starknet invoke --function set_random_names --address 0x039930ebf6ecb2d31b60f24e5729de95f63df86556cf20e163ed94213ce7000d --account version_2 --max_fee 10000000000000000 --input 100 1477539817190980062013511436222722368611442480 1477539817190980062013511436222722368611442481 1477539817190980062013511436222722368611442482 1477539817190980062013511436222722368611442483 1477539817190980062013511436222722368611442484 1477539817190980062013511436222722368611442485 1477539817190980062013511436222722368611442486 1477539817190980062013511436222722368611442487 1477539817190980062013511436222722368611442488 1477539817190980062013511436222722368611442489 378250193200890895875458927673016926364529275184 378250193200890895875458927673016926364529275185 378250193200890895875458927673016926364529275186 378250193200890895875458927673016926364529275187 378250193200890895875458927673016926364529275188 378250193200890895875458927673016926364529275189 378250193200890895875458927673016926364529275190 378250193200890895875458927673016926364529275191 378250193200890895875458927673016926364529275192 378250193200890895875458927673016926364529275193 378250193200890895875458927673016926364529275440 378250193200890895875458927673016926364529275441 378250193200890895875458927673016926364529275442 378250193200890895875458927673016926364529275443 378250193200890895875458927673016926364529275444 378250193200890895875458927673016926364529275445 378250193200890895875458927673016926364529275446 378250193200890895875458927673016926364529275447 378250193200890895875458927673016926364529275448 378250193200890895875458927673016926364529275449 378250193200890895875458927673016926364529275696 378250193200890895875458927673016926364529275697 378250193200890895875458927673016926364529275698 378250193200890895875458927673016926364529275699 378250193200890895875458927673016926364529275700 378250193200890895875458927673016926364529275701 378250193200890895875458927673016926364529275702 378250193200890895875458927673016926364529275703 378250193200890895875458927673016926364529275704 378250193200890895875458927673016926364529275705 378250193200890895875458927673016926364529275952 378250193200890895875458927673016926364529275953 378250193200890895875458927673016926364529275954 378250193200890895875458927673016926364529275955 378250193200890895875458927673016926364529275956 378250193200890895875458927673016926364529275957 378250193200890895875458927673016926364529275958 378250193200890895875458927673016926364529275959 378250193200890895875458927673016926364529275960 378250193200890895875458927673016926364529275961 378250193200890895875458927673016926364529276208 378250193200890895875458927673016926364529276209 378250193200890895875458927673016926364529276210 378250193200890895875458927673016926364529276211 378250193200890895875458927673016926364529276212 378250193200890895875458927673016926364529276213 378250193200890895875458927673016926364529276214 378250193200890895875458927673016926364529276215 378250193200890895875458927673016926364529276216 378250193200890895875458927673016926364529276217 378250193200890895875458927673016926364529276464 378250193200890895875458927673016926364529276465 378250193200890895875458927673016926364529276466 378250193200890895875458927673016926364529276467 378250193200890895875458927673016926364529276468 378250193200890895875458927673016926364529276469 378250193200890895875458927673016926364529276470 378250193200890895875458927673016926364529276471 378250193200890895875458927673016926364529276472 378250193200890895875458927673016926364529276473 378250193200890895875458927673016926364529276720 378250193200890895875458927673016926364529276721 378250193200890895875458927673016926364529276722 378250193200890895875458927673016926364529276723 378250193200890895875458927673016926364529276724 378250193200890895875458927673016926364529276725 378250193200890895875458927673016926364529276726 378250193200890895875458927673016926364529276727 378250193200890895875458927673016926364529276728 378250193200890895875458927673016926364529276729 378250193200890895875458927673016926364529276976 378250193200890895875458927673016926364529276977 378250193200890895875458927673016926364529276978 378250193200890895875458927673016926364529276979 378250193200890895875458927673016926364529276980 378250193200890895875458927673016926364529276981 378250193200890895875458927673016926364529276982 378250193200890895875458927673016926364529276983 378250193200890895875458927673016926364529276984 378250193200890895875458927673016926364529276985 378250193200890895875458927673016926364529277232 378250193200890895875458927673016926364529277233 378250193200890895875458927673016926364529277234 378250193200890895875458927673016926364529277235 378250193200890895875458927673016926364529277236 378250193200890895875458927673016926364529277237 378250193200890895875458927673016926364529277238 378250193200890895875458927673016926364529277239 378250193200890895875458927673016926364529277240 378250193200890895875458927673016926364529277241 -``` - -Setting random symbols: - -``` -starknet invoke --function set_random_symbols --address 0x039930ebf6ecb2d31b60f24e5729de95f63df86556cf20e163ed94213ce7000d --account version_2 --max_fee 10000000000000000 --input 100 18668896499556144 18668896499556145 18668896499556146 18668896499556147 18668896499556148 18668896499556149 18668896499556150 18668896499556151 18668896499556152 18668896499556153 4779237503886373168 4779237503886373169 4779237503886373170 4779237503886373171 4779237503886373172 4779237503886373173 4779237503886373174 4779237503886373175 4779237503886373176 4779237503886373177 4779237503886373424 4779237503886373425 4779237503886373426 4779237503886373427 4779237503886373428 4779237503886373429 4779237503886373430 4779237503886373431 4779237503886373432 4779237503886373433 4779237503886373680 4779237503886373681 4779237503886373682 4779237503886373683 4779237503886373684 4779237503886373685 4779237503886373686 4779237503886373687 4779237503886373688 4779237503886373689 4779237503886373936 4779237503886373937 4779237503886373938 4779237503886373939 4779237503886373940 4779237503886373941 4779237503886373942 4779237503886373943 4779237503886373944 4779237503886373945 4779237503886374192 4779237503886374193 4779237503886374194 4779237503886374195 4779237503886374196 4779237503886374197 4779237503886374198 4779237503886374199 4779237503886374200 4779237503886374201 4779237503886374448 4779237503886374449 4779237503886374450 4779237503886374451 4779237503886374452 4779237503886374453 4779237503886374454 4779237503886374455 4779237503886374456 4779237503886374457 4779237503886374704 4779237503886374705 4779237503886374706 4779237503886374707 4779237503886374708 4779237503886374709 4779237503886374710 4779237503886374711 4779237503886374712 4779237503886374713 4779237503886374960 4779237503886374961 4779237503886374962 4779237503886374963 4779237503886374964 4779237503886374965 4779237503886374966 4779237503886374967 4779237503886374968 4779237503886374969 4779237503886375216 4779237503886375217 4779237503886375218 4779237503886375219 4779237503886375220 4779237503886375221 4779237503886375222 4779237503886375223 4779237503886375224 4779237503886375225 - -``` diff --git a/src/token/TDERC20.cairo b/src/token/TDERC20.cairo index 281b112..e1e2325 100644 --- a/src/token/TDERC20.cairo +++ b/src/token/TDERC20.cairo @@ -36,7 +36,6 @@ mod TDERC20 { use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transfer; use starknet_erc721::token::ERC20_base::ERC20Base::ERC20_transferFrom; use starknet_erc721::utils::helper; - use starknet_erc721::utils::helper::check_boolean; struct Storage { is_transferable_storage: bool, @@ -191,12 +190,12 @@ mod TDERC20 { fn only_teacher_or_exercise() { let caller = get_caller_address(); let permission = teachers_and_exercises_accounts::read(caller); - assert(check_boolean(permission) == check_boolean(true), 'NO_PERMISSION'); + assert(permission, 'NO_PERMISSION'); } fn _is_transferable() { let permission = is_transferable_storage::read(); - assert(check_boolean(permission) == check_boolean(true), 'NOT_TRANSFERABLE'); + assert(permission, 'NOT_TRANSFERABLE'); } #[external] fn update_class_hash_by_admin(class_hash_in_felt: felt252) { diff --git a/src/utils/ex00_base.cairo b/src/utils/ex00_base.cairo index 873fd7d..d3a8ccf 100644 --- a/src/utils/ex00_base.cairo +++ b/src/utils/ex00_base.cairo @@ -26,7 +26,6 @@ mod Ex00Base { use starknet_erc721::utils::Iplayers_registry::Iplayers_registryDispatcher; use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; - use starknet_erc721::utils::helper::check_boolean; const Decimals: u128 = 1000000000000000000_u128; @@ -99,17 +98,17 @@ mod Ex00Base { .distribute_points(to, points_to_credit); } - fn validate_exercise(account: ContractAddress) { + fn validate_exercise(account: ContractAddress, exercise_id: u128) { // 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 exercise_id = exercise_id_storage::read(); let has_current_user_validated_exercise = Iplayers_registryDispatcher{contract_address: players_registry} .has_validated_exercise(account, workshop_id, exercise_id); - assert(check_boolean(has_current_user_validated_exercise) == check_boolean(false), 'Exercise previously validated'); + assert(!has_current_user_validated_exercise, 'Exercise previously validated'); Iplayers_registryDispatcher{contract_address: players_registry} .validate_exercise(account, workshop_id, exercise_id); } @@ -121,7 +120,7 @@ mod Ex00Base { let is_admin = Iplayers_registryDispatcher{contract_address: players_registry} .is_exercise_or_admin(sender_address); - assert (check_boolean(is_admin) == check_boolean(true), 'CALLER_NO_ADMIN_RIGHTS'); + assert (is_admin, 'CALLER_NO_ADMIN_RIGHTS'); let class_hash: ClassHash = class_hash_in_felt.try_into().unwrap(); replace_class_syscall(class_hash); } diff --git a/src/utils/helper.py b/src/utils/helper.py index 949c41e..7dd6604 100644 --- a/src/utils/helper.py +++ b/src/utils/helper.py @@ -11,8 +11,8 @@ def str_to_felt(text): data_symbol = [] for i in range(0, 100): - data_name.append(str_to_felt(f"BASECAMP_04_TOKEN_{i}")) - data_symbol.append(str_to_felt(f"BSC04_{i}")) + data_name.append(str_to_felt(f"ERC721_WORKSHOP{i}")) + data_symbol.append(str_to_felt(f"ERC721W_{i}")) print(len(data_symbol)) diff --git a/src/utils/players_registry.cairo b/src/utils/players_registry.cairo index 7218759..77fef28 100644 --- a/src/utils/players_registry.cairo +++ b/src/utils/players_registry.cairo @@ -26,7 +26,6 @@ mod PlayersRegistry { use starknet_erc721::token::ITDERC20::ITDERC20DispatcherTrait; use starknet_erc721::token::ITDERC20::ITDERC20Dispatcher; use starknet_erc721::utils::helper; - use starknet_erc721::utils::helper::check_boolean; //////////////////////////////// // STORAGE @@ -126,7 +125,7 @@ mod PlayersRegistry { (account, workshop, exercise) ); - assert(check_boolean(is_validated) == check_boolean(false), 'USER_VALIDATED'); + assert(!is_validated, 'USER_VALIDATED'); // Marking the exercise as completed has_validated_exercise_storage::write((account, workshop, exercise), true); @@ -154,7 +153,7 @@ mod PlayersRegistry { fn only_exercise_or_admin() { let caller: ContractAddress = get_caller_address(); let permission: bool = exercises_and_admins_accounts::read(caller); - assert (check_boolean(permission) == check_boolean(true), 'You dont have permission.'); + assert (permission, 'You dont have permission.'); } diff --git a/src/utils/sample_name.json b/src/utils/sample_name.json index 4a4b409..fa98dc4 100644 --- a/src/utils/sample_name.json +++ b/src/utils/sample_name.json @@ -1 +1 @@ -[1477539817190980062013511436222722368611442480 1477539817190980062013511436222722368611442481 1477539817190980062013511436222722368611442482 1477539817190980062013511436222722368611442483 1477539817190980062013511436222722368611442484 1477539817190980062013511436222722368611442485 1477539817190980062013511436222722368611442486 1477539817190980062013511436222722368611442487 1477539817190980062013511436222722368611442488 1477539817190980062013511436222722368611442489 378250193200890895875458927673016926364529275184 378250193200890895875458927673016926364529275185 378250193200890895875458927673016926364529275186 378250193200890895875458927673016926364529275187 378250193200890895875458927673016926364529275188 378250193200890895875458927673016926364529275189 378250193200890895875458927673016926364529275190 378250193200890895875458927673016926364529275191 378250193200890895875458927673016926364529275192 378250193200890895875458927673016926364529275193 378250193200890895875458927673016926364529275440 378250193200890895875458927673016926364529275441 378250193200890895875458927673016926364529275442 378250193200890895875458927673016926364529275443 378250193200890895875458927673016926364529275444 378250193200890895875458927673016926364529275445 378250193200890895875458927673016926364529275446 378250193200890895875458927673016926364529275447 378250193200890895875458927673016926364529275448 378250193200890895875458927673016926364529275449 378250193200890895875458927673016926364529275696 378250193200890895875458927673016926364529275697 378250193200890895875458927673016926364529275698 378250193200890895875458927673016926364529275699 378250193200890895875458927673016926364529275700 378250193200890895875458927673016926364529275701 378250193200890895875458927673016926364529275702 378250193200890895875458927673016926364529275703 378250193200890895875458927673016926364529275704 378250193200890895875458927673016926364529275705 378250193200890895875458927673016926364529275952 378250193200890895875458927673016926364529275953 378250193200890895875458927673016926364529275954 378250193200890895875458927673016926364529275955 378250193200890895875458927673016926364529275956 378250193200890895875458927673016926364529275957 378250193200890895875458927673016926364529275958 378250193200890895875458927673016926364529275959 378250193200890895875458927673016926364529275960 378250193200890895875458927673016926364529275961 378250193200890895875458927673016926364529276208 378250193200890895875458927673016926364529276209 378250193200890895875458927673016926364529276210 378250193200890895875458927673016926364529276211 378250193200890895875458927673016926364529276212 378250193200890895875458927673016926364529276213 378250193200890895875458927673016926364529276214 378250193200890895875458927673016926364529276215 378250193200890895875458927673016926364529276216 378250193200890895875458927673016926364529276217 378250193200890895875458927673016926364529276464 378250193200890895875458927673016926364529276465 378250193200890895875458927673016926364529276466 378250193200890895875458927673016926364529276467 378250193200890895875458927673016926364529276468 378250193200890895875458927673016926364529276469 378250193200890895875458927673016926364529276470 378250193200890895875458927673016926364529276471 378250193200890895875458927673016926364529276472 378250193200890895875458927673016926364529276473 378250193200890895875458927673016926364529276720 378250193200890895875458927673016926364529276721 378250193200890895875458927673016926364529276722 378250193200890895875458927673016926364529276723 378250193200890895875458927673016926364529276724 378250193200890895875458927673016926364529276725 378250193200890895875458927673016926364529276726 378250193200890895875458927673016926364529276727 378250193200890895875458927673016926364529276728 378250193200890895875458927673016926364529276729 378250193200890895875458927673016926364529276976 378250193200890895875458927673016926364529276977 378250193200890895875458927673016926364529276978 378250193200890895875458927673016926364529276979 378250193200890895875458927673016926364529276980 378250193200890895875458927673016926364529276981 378250193200890895875458927673016926364529276982 378250193200890895875458927673016926364529276983 378250193200890895875458927673016926364529276984 378250193200890895875458927673016926364529276985 378250193200890895875458927673016926364529277232 378250193200890895875458927673016926364529277233 378250193200890895875458927673016926364529277234 378250193200890895875458927673016926364529277235 378250193200890895875458927673016926364529277236 378250193200890895875458927673016926364529277237 378250193200890895875458927673016926364529277238 378250193200890895875458927673016926364529277239 378250193200890895875458927673016926364529277240 378250193200890895875458927673016926364529277241] \ No newline at end of file +[92143863346085372133985850962073309232 92143863346085372133985850962073309233 92143863346085372133985850962073309234 92143863346085372133985850962073309235 92143863346085372133985850962073309236 92143863346085372133985850962073309237 92143863346085372133985850962073309238 92143863346085372133985850962073309239 92143863346085372133985850962073309240 92143863346085372133985850962073309241 23588829016597855266300377846290767163696 23588829016597855266300377846290767163697 23588829016597855266300377846290767163698 23588829016597855266300377846290767163699 23588829016597855266300377846290767163700 23588829016597855266300377846290767163701 23588829016597855266300377846290767163702 23588829016597855266300377846290767163703 23588829016597855266300377846290767163704 23588829016597855266300377846290767163705 23588829016597855266300377846290767163952 23588829016597855266300377846290767163953 23588829016597855266300377846290767163954 23588829016597855266300377846290767163955 23588829016597855266300377846290767163956 23588829016597855266300377846290767163957 23588829016597855266300377846290767163958 23588829016597855266300377846290767163959 23588829016597855266300377846290767163960 23588829016597855266300377846290767163961 23588829016597855266300377846290767164208 23588829016597855266300377846290767164209 23588829016597855266300377846290767164210 23588829016597855266300377846290767164211 23588829016597855266300377846290767164212 23588829016597855266300377846290767164213 23588829016597855266300377846290767164214 23588829016597855266300377846290767164215 23588829016597855266300377846290767164216 23588829016597855266300377846290767164217 23588829016597855266300377846290767164464 23588829016597855266300377846290767164465 23588829016597855266300377846290767164466 23588829016597855266300377846290767164467 23588829016597855266300377846290767164468 23588829016597855266300377846290767164469 23588829016597855266300377846290767164470 23588829016597855266300377846290767164471 23588829016597855266300377846290767164472 23588829016597855266300377846290767164473 23588829016597855266300377846290767164720 23588829016597855266300377846290767164721 23588829016597855266300377846290767164722 23588829016597855266300377846290767164723 23588829016597855266300377846290767164724 23588829016597855266300377846290767164725 23588829016597855266300377846290767164726 23588829016597855266300377846290767164727 23588829016597855266300377846290767164728 23588829016597855266300377846290767164729 23588829016597855266300377846290767164976 23588829016597855266300377846290767164977 23588829016597855266300377846290767164978 23588829016597855266300377846290767164979 23588829016597855266300377846290767164980 23588829016597855266300377846290767164981 23588829016597855266300377846290767164982 23588829016597855266300377846290767164983 23588829016597855266300377846290767164984 23588829016597855266300377846290767164985 23588829016597855266300377846290767165232 23588829016597855266300377846290767165233 23588829016597855266300377846290767165234 23588829016597855266300377846290767165235 23588829016597855266300377846290767165236 23588829016597855266300377846290767165237 23588829016597855266300377846290767165238 23588829016597855266300377846290767165239 23588829016597855266300377846290767165240 23588829016597855266300377846290767165241 23588829016597855266300377846290767165488 23588829016597855266300377846290767165489 23588829016597855266300377846290767165490 23588829016597855266300377846290767165491 23588829016597855266300377846290767165492 23588829016597855266300377846290767165493 23588829016597855266300377846290767165494 23588829016597855266300377846290767165495 23588829016597855266300377846290767165496 23588829016597855266300377846290767165497 23588829016597855266300377846290767165744 23588829016597855266300377846290767165745 23588829016597855266300377846290767165746 23588829016597855266300377846290767165747 23588829016597855266300377846290767165748 23588829016597855266300377846290767165749 23588829016597855266300377846290767165750 23588829016597855266300377846290767165751 23588829016597855266300377846290767165752 23588829016597855266300377846290767165753] \ No newline at end of file diff --git a/src/utils/sample_symbol.json b/src/utils/sample_symbol.json index 4642602..bf32296 100644 --- a/src/utils/sample_symbol.json +++ b/src/utils/sample_symbol.json @@ -1 +1 @@ -[18668896499556144 18668896499556145 18668896499556146 18668896499556147 18668896499556148 18668896499556149 18668896499556150 18668896499556151 18668896499556152 18668896499556153 4779237503886373168 4779237503886373169 4779237503886373170 4779237503886373171 4779237503886373172 4779237503886373173 4779237503886373174 4779237503886373175 4779237503886373176 4779237503886373177 4779237503886373424 4779237503886373425 4779237503886373426 4779237503886373427 4779237503886373428 4779237503886373429 4779237503886373430 4779237503886373431 4779237503886373432 4779237503886373433 4779237503886373680 4779237503886373681 4779237503886373682 4779237503886373683 4779237503886373684 4779237503886373685 4779237503886373686 4779237503886373687 4779237503886373688 4779237503886373689 4779237503886373936 4779237503886373937 4779237503886373938 4779237503886373939 4779237503886373940 4779237503886373941 4779237503886373942 4779237503886373943 4779237503886373944 4779237503886373945 4779237503886374192 4779237503886374193 4779237503886374194 4779237503886374195 4779237503886374196 4779237503886374197 4779237503886374198 4779237503886374199 4779237503886374200 4779237503886374201 4779237503886374448 4779237503886374449 4779237503886374450 4779237503886374451 4779237503886374452 4779237503886374453 4779237503886374454 4779237503886374455 4779237503886374456 4779237503886374457 4779237503886374704 4779237503886374705 4779237503886374706 4779237503886374707 4779237503886374708 4779237503886374709 4779237503886374710 4779237503886374711 4779237503886374712 4779237503886374713 4779237503886374960 4779237503886374961 4779237503886374962 4779237503886374963 4779237503886374964 4779237503886374965 4779237503886374966 4779237503886374967 4779237503886374968 4779237503886374969 4779237503886375216 4779237503886375217 4779237503886375218 4779237503886375219 4779237503886375220 4779237503886375221 4779237503886375222 4779237503886375223 4779237503886375224 4779237503886375225] \ No newline at end of file +[1278752983309224468272 1278752983309224468273 1278752983309224468274 1278752983309224468275 1278752983309224468276 1278752983309224468277 1278752983309224468278 1278752983309224468279 1278752983309224468280 1278752983309224468281 327360763727161463877936 327360763727161463877937 327360763727161463877938 327360763727161463877939 327360763727161463877940 327360763727161463877941 327360763727161463877942 327360763727161463877943 327360763727161463877944 327360763727161463877945 327360763727161463878192 327360763727161463878193 327360763727161463878194 327360763727161463878195 327360763727161463878196 327360763727161463878197 327360763727161463878198 327360763727161463878199 327360763727161463878200 327360763727161463878201 327360763727161463878448 327360763727161463878449 327360763727161463878450 327360763727161463878451 327360763727161463878452 327360763727161463878453 327360763727161463878454 327360763727161463878455 327360763727161463878456 327360763727161463878457 327360763727161463878704 327360763727161463878705 327360763727161463878706 327360763727161463878707 327360763727161463878708 327360763727161463878709 327360763727161463878710 327360763727161463878711 327360763727161463878712 327360763727161463878713 327360763727161463878960 327360763727161463878961 327360763727161463878962 327360763727161463878963 327360763727161463878964 327360763727161463878965 327360763727161463878966 327360763727161463878967 327360763727161463878968 327360763727161463878969 327360763727161463879216 327360763727161463879217 327360763727161463879218 327360763727161463879219 327360763727161463879220 327360763727161463879221 327360763727161463879222 327360763727161463879223 327360763727161463879224 327360763727161463879225 327360763727161463879472 327360763727161463879473 327360763727161463879474 327360763727161463879475 327360763727161463879476 327360763727161463879477 327360763727161463879478 327360763727161463879479 327360763727161463879480 327360763727161463879481 327360763727161463879728 327360763727161463879729 327360763727161463879730 327360763727161463879731 327360763727161463879732 327360763727161463879733 327360763727161463879734 327360763727161463879735 327360763727161463879736 327360763727161463879737 327360763727161463879984 327360763727161463879985 327360763727161463879986 327360763727161463879987 327360763727161463879988 327360763727161463879989 327360763727161463879990 327360763727161463879991 327360763727161463879992 327360763727161463879993] \ No newline at end of file From 4c410e9d9dc572036148649ea4a7b13eda00ea5b Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 13:33:08 +0200 Subject: [PATCH 05/11] removed cairo-0 and moved it to it's own branch. updated readme --- assets/1.json | 1 - assets/10.json | 1 - assets/100.json | 1 - assets/11.json | 1 - assets/12.json | 1 - assets/13.json | 1 - assets/14.json | 1 - assets/15.json | 1 - assets/16.json | 1 - assets/17.json | 1 - assets/18.json | 1 - assets/19.json | 1 - assets/2.json | 1 - assets/20.json | 1 - assets/21.json | 1 - assets/22.json | 1 - assets/23.json | 1 - assets/24.json | 1 - assets/25.json | 1 - assets/26.json | 1 - assets/27.json | 1 - assets/28.json | 1 - assets/29.json | 1 - assets/3.json | 1 - assets/30.json | 1 - assets/31.json | 1 - assets/32.json | 1 - assets/33.json | 1 - assets/34.json | 1 - assets/35.json | 1 - assets/36.json | 1 - assets/37.json | 1 - assets/38.json | 1 - assets/39.json | 1 - assets/4.json | 1 - assets/40.json | 1 - assets/41.json | 1 - assets/42.json | 1 - assets/43.json | 1 - assets/44.json | 1 - assets/45.json | 1 - assets/46.json | 1 - assets/47.json | 1 - assets/48.json | 1 - assets/49.json | 1 - assets/5.json | 1 - assets/50.json | 1 - assets/51.json | 1 - assets/52.json | 1 - assets/53.json | 1 - assets/54.json | 1 - assets/55.json | 1 - assets/56.json | 1 - assets/57.json | 1 - assets/58.json | 1 - assets/59.json | 1 - assets/6.json | 1 - assets/60.json | 1 - assets/61.json | 1 - assets/62.json | 1 - assets/63.json | 1 - assets/64.json | 1 - assets/65.json | 1 - assets/66.json | 1 - assets/67.json | 1 - assets/68.json | 1 - assets/69.json | 1 - assets/7.json | 1 - assets/70.json | 1 - assets/71.json | 1 - assets/72.json | 1 - assets/73.json | 1 - assets/74.json | 1 - assets/75.json | 1 - assets/76.json | 1 - assets/77.json | 1 - assets/78.json | 1 - assets/79.json | 1 - assets/8.json | 1 - assets/80.json | 1 - assets/81.json | 1 - assets/82.json | 1 - assets/83.json | 1 - assets/84.json | 1 - assets/85.json | 1 - assets/86.json | 1 - assets/87.json | 1 - assets/88.json | 1 - assets/89.json | 1 - assets/9.json | 1 - assets/90.json | 1 - assets/91.json | 1 - assets/92.json | 1 - assets/93.json | 1 - assets/94.json | 1 - assets/95.json | 1 - assets/96.json | 1 - assets/97.json | 1 - assets/98.json | 1 - assets/99.json | 1 - contracts/Evaluator.cairo | 779 ------------------ contracts/IExerciseSolution.cairo | 22 - contracts/token/ERC20/IERC20.cairo | 33 - contracts/token/ERC20/ITDERC20.cairo | 24 - contracts/token/ERC20/TDERC20.cairo | 222 ----- contracts/token/ERC20/dummy_token.cairo | 122 --- contracts/token/ERC721/ERC721.cairo | 105 --- .../token/ERC721/ERC721_Metadata_base.cairo | 98 --- contracts/token/ERC721/ERC721_metadata.cairo | 174 ---- contracts/token/ERC721/IERC721.cairo | 30 - contracts/token/ERC721/IERC721_Receiver.cairo | 11 - contracts/token/ERC721/IERC721_metadata.cairo | 33 - .../token/ERC721/TDERC721_metadata.cairo | 209 ----- contracts/utils/Array.cairo | 14 - contracts/utils/Array_sekai.cairo | 16 - contracts/utils/Iplayers_registry.cairo | 27 - contracts/utils/ShortString.cairo | 141 ---- contracts/utils/String.cairo | 295 ------- contracts/utils/ex00_base.cairo | 160 ---- contracts/utils/players_registry.cairo | 213 ----- deploy/deploying.txt | 30 - .../deployment-testnet1.md | 1 - deploy/genJsonMetadata.py | 10 - deploy/genRandArgs.py | 8 - {src/utils => deploy}/helper.py | 0 {src/utils => deploy}/sample_name.json | 0 {src/utils => deploy}/sample_symbol.json | 0 src/README.md | 89 +- 128 files changed, 81 insertions(+), 2885 deletions(-) delete mode 100644 assets/1.json delete mode 100644 assets/10.json delete mode 100644 assets/100.json delete mode 100644 assets/11.json delete mode 100644 assets/12.json delete mode 100644 assets/13.json delete mode 100644 assets/14.json delete mode 100644 assets/15.json delete mode 100644 assets/16.json delete mode 100644 assets/17.json delete mode 100644 assets/18.json delete mode 100644 assets/19.json delete mode 100644 assets/2.json delete mode 100644 assets/20.json delete mode 100644 assets/21.json delete mode 100644 assets/22.json delete mode 100644 assets/23.json delete mode 100644 assets/24.json delete mode 100644 assets/25.json delete mode 100644 assets/26.json delete mode 100644 assets/27.json delete mode 100644 assets/28.json delete mode 100644 assets/29.json delete mode 100644 assets/3.json delete mode 100644 assets/30.json delete mode 100644 assets/31.json delete mode 100644 assets/32.json delete mode 100644 assets/33.json delete mode 100644 assets/34.json delete mode 100644 assets/35.json delete mode 100644 assets/36.json delete mode 100644 assets/37.json delete mode 100644 assets/38.json delete mode 100644 assets/39.json delete mode 100644 assets/4.json delete mode 100644 assets/40.json delete mode 100644 assets/41.json delete mode 100644 assets/42.json delete mode 100644 assets/43.json delete mode 100644 assets/44.json delete mode 100644 assets/45.json delete mode 100644 assets/46.json delete mode 100644 assets/47.json delete mode 100644 assets/48.json delete mode 100644 assets/49.json delete mode 100644 assets/5.json delete mode 100644 assets/50.json delete mode 100644 assets/51.json delete mode 100644 assets/52.json delete mode 100644 assets/53.json delete mode 100644 assets/54.json delete mode 100644 assets/55.json delete mode 100644 assets/56.json delete mode 100644 assets/57.json delete mode 100644 assets/58.json delete mode 100644 assets/59.json delete mode 100644 assets/6.json delete mode 100644 assets/60.json delete mode 100644 assets/61.json delete mode 100644 assets/62.json delete mode 100644 assets/63.json delete mode 100644 assets/64.json delete mode 100644 assets/65.json delete mode 100644 assets/66.json delete mode 100644 assets/67.json delete mode 100644 assets/68.json delete mode 100644 assets/69.json delete mode 100644 assets/7.json delete mode 100644 assets/70.json delete mode 100644 assets/71.json delete mode 100644 assets/72.json delete mode 100644 assets/73.json delete mode 100644 assets/74.json delete mode 100644 assets/75.json delete mode 100644 assets/76.json delete mode 100644 assets/77.json delete mode 100644 assets/78.json delete mode 100644 assets/79.json delete mode 100644 assets/8.json delete mode 100644 assets/80.json delete mode 100644 assets/81.json delete mode 100644 assets/82.json delete mode 100644 assets/83.json delete mode 100644 assets/84.json delete mode 100644 assets/85.json delete mode 100644 assets/86.json delete mode 100644 assets/87.json delete mode 100644 assets/88.json delete mode 100644 assets/89.json delete mode 100644 assets/9.json delete mode 100644 assets/90.json delete mode 100644 assets/91.json delete mode 100644 assets/92.json delete mode 100644 assets/93.json delete mode 100644 assets/94.json delete mode 100644 assets/95.json delete mode 100644 assets/96.json delete mode 100644 assets/97.json delete mode 100644 assets/98.json delete mode 100644 assets/99.json delete mode 100644 contracts/Evaluator.cairo delete mode 100644 contracts/IExerciseSolution.cairo delete mode 100644 contracts/token/ERC20/IERC20.cairo delete mode 100644 contracts/token/ERC20/ITDERC20.cairo delete mode 100644 contracts/token/ERC20/TDERC20.cairo delete mode 100644 contracts/token/ERC20/dummy_token.cairo delete mode 100644 contracts/token/ERC721/ERC721.cairo delete mode 100644 contracts/token/ERC721/ERC721_Metadata_base.cairo delete mode 100644 contracts/token/ERC721/ERC721_metadata.cairo delete mode 100644 contracts/token/ERC721/IERC721.cairo delete mode 100644 contracts/token/ERC721/IERC721_Receiver.cairo delete mode 100644 contracts/token/ERC721/IERC721_metadata.cairo delete mode 100644 contracts/token/ERC721/TDERC721_metadata.cairo delete mode 100644 contracts/utils/Array.cairo delete mode 100644 contracts/utils/Array_sekai.cairo delete mode 100644 contracts/utils/Iplayers_registry.cairo delete mode 100644 contracts/utils/ShortString.cairo delete mode 100644 contracts/utils/String.cairo delete mode 100644 contracts/utils/ex00_base.cairo delete mode 100644 contracts/utils/players_registry.cairo delete mode 100644 deploy/deploying.txt rename src/deploy_doc.md => deploy/deployment-testnet1.md (98%) delete mode 100644 deploy/genJsonMetadata.py delete mode 100644 deploy/genRandArgs.py rename {src/utils => deploy}/helper.py (100%) rename {src/utils => deploy}/sample_name.json (100%) rename {src/utils => deploy}/sample_symbol.json (100%) diff --git a/assets/1.json b/assets/1.json deleted file mode 100644 index e930668..0000000 --- a/assets/1.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 1", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/1.jpeg"} \ No newline at end of file diff --git a/assets/10.json b/assets/10.json deleted file mode 100644 index 6bea37d..0000000 --- a/assets/10.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 10", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/10.jpeg"} \ No newline at end of file diff --git a/assets/100.json b/assets/100.json deleted file mode 100644 index a2a2f46..0000000 --- a/assets/100.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 100", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/100.jpeg"} \ No newline at end of file diff --git a/assets/11.json b/assets/11.json deleted file mode 100644 index 3a5df6b..0000000 --- a/assets/11.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 11", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/11.jpeg"} \ No newline at end of file diff --git a/assets/12.json b/assets/12.json deleted file mode 100644 index f56fafa..0000000 --- a/assets/12.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 12", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/12.jpeg"} \ No newline at end of file diff --git a/assets/13.json b/assets/13.json deleted file mode 100644 index 6e6d2bd..0000000 --- a/assets/13.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 13", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/13.jpeg"} \ No newline at end of file diff --git a/assets/14.json b/assets/14.json deleted file mode 100644 index 006588a..0000000 --- a/assets/14.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 14", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/14.jpeg"} \ No newline at end of file diff --git a/assets/15.json b/assets/15.json deleted file mode 100644 index 7852421..0000000 --- a/assets/15.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 15", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/15.jpeg"} \ No newline at end of file diff --git a/assets/16.json b/assets/16.json deleted file mode 100644 index 71f249d..0000000 --- a/assets/16.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 16", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/16.jpeg"} \ No newline at end of file diff --git a/assets/17.json b/assets/17.json deleted file mode 100644 index f1afd38..0000000 --- a/assets/17.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 17", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/17.jpeg"} \ No newline at end of file diff --git a/assets/18.json b/assets/18.json deleted file mode 100644 index da54626..0000000 --- a/assets/18.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 18", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/18.jpeg"} \ No newline at end of file diff --git a/assets/19.json b/assets/19.json deleted file mode 100644 index 06bc123..0000000 --- a/assets/19.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 19", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/19.jpeg"} \ No newline at end of file diff --git a/assets/2.json b/assets/2.json deleted file mode 100644 index 6a98f9e..0000000 --- a/assets/2.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 2", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/2.jpeg"} \ No newline at end of file diff --git a/assets/20.json b/assets/20.json deleted file mode 100644 index 7a1f5b3..0000000 --- a/assets/20.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 20", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/20.jpeg"} \ No newline at end of file diff --git a/assets/21.json b/assets/21.json deleted file mode 100644 index 5475f79..0000000 --- a/assets/21.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 21", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/21.jpeg"} \ No newline at end of file diff --git a/assets/22.json b/assets/22.json deleted file mode 100644 index cb23565..0000000 --- a/assets/22.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 22", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/22.jpeg"} \ No newline at end of file diff --git a/assets/23.json b/assets/23.json deleted file mode 100644 index 43976bd..0000000 --- a/assets/23.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 23", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/23.jpeg"} \ No newline at end of file diff --git a/assets/24.json b/assets/24.json deleted file mode 100644 index 0b16792..0000000 --- a/assets/24.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 24", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/24.jpeg"} \ No newline at end of file diff --git a/assets/25.json b/assets/25.json deleted file mode 100644 index bb637b3..0000000 --- a/assets/25.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 25", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/25.jpeg"} \ No newline at end of file diff --git a/assets/26.json b/assets/26.json deleted file mode 100644 index d2d9599..0000000 --- a/assets/26.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 26", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/26.jpeg"} \ No newline at end of file diff --git a/assets/27.json b/assets/27.json deleted file mode 100644 index faa5cc4..0000000 --- a/assets/27.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 27", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/27.jpeg"} \ No newline at end of file diff --git a/assets/28.json b/assets/28.json deleted file mode 100644 index f555c74..0000000 --- a/assets/28.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 28", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/28.jpeg"} \ No newline at end of file diff --git a/assets/29.json b/assets/29.json deleted file mode 100644 index 5b80b4d..0000000 --- a/assets/29.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 29", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/29.jpeg"} \ No newline at end of file diff --git a/assets/3.json b/assets/3.json deleted file mode 100644 index 035ee44..0000000 --- a/assets/3.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 3", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/3.jpeg"} \ No newline at end of file diff --git a/assets/30.json b/assets/30.json deleted file mode 100644 index 527e337..0000000 --- a/assets/30.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 30", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/30.jpeg"} \ No newline at end of file diff --git a/assets/31.json b/assets/31.json deleted file mode 100644 index 13cda8e..0000000 --- a/assets/31.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 31", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/31.jpeg"} \ No newline at end of file diff --git a/assets/32.json b/assets/32.json deleted file mode 100644 index e2104b9..0000000 --- a/assets/32.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 32", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/32.jpeg"} \ No newline at end of file diff --git a/assets/33.json b/assets/33.json deleted file mode 100644 index f21c379..0000000 --- a/assets/33.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 33", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/33.jpeg"} \ No newline at end of file diff --git a/assets/34.json b/assets/34.json deleted file mode 100644 index 2c110d4..0000000 --- a/assets/34.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 34", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/34.jpeg"} \ No newline at end of file diff --git a/assets/35.json b/assets/35.json deleted file mode 100644 index ac0973d..0000000 --- a/assets/35.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 35", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/35.jpeg"} \ No newline at end of file diff --git a/assets/36.json b/assets/36.json deleted file mode 100644 index 888b373..0000000 --- a/assets/36.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 36", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/36.jpeg"} \ No newline at end of file diff --git a/assets/37.json b/assets/37.json deleted file mode 100644 index d1edd28..0000000 --- a/assets/37.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 37", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/37.jpeg"} \ No newline at end of file diff --git a/assets/38.json b/assets/38.json deleted file mode 100644 index 69ba764..0000000 --- a/assets/38.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 38", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/38.jpeg"} \ No newline at end of file diff --git a/assets/39.json b/assets/39.json deleted file mode 100644 index dfa60dc..0000000 --- a/assets/39.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 39", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/39.jpeg"} \ No newline at end of file diff --git a/assets/4.json b/assets/4.json deleted file mode 100644 index 0750330..0000000 --- a/assets/4.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 4", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/4.jpeg"} \ No newline at end of file diff --git a/assets/40.json b/assets/40.json deleted file mode 100644 index b6d8b11..0000000 --- a/assets/40.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 40", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/40.jpeg"} \ No newline at end of file diff --git a/assets/41.json b/assets/41.json deleted file mode 100644 index d0585f9..0000000 --- a/assets/41.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 41", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/41.jpeg"} \ No newline at end of file diff --git a/assets/42.json b/assets/42.json deleted file mode 100644 index 70357f9..0000000 --- a/assets/42.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 42", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/42.jpeg"} \ No newline at end of file diff --git a/assets/43.json b/assets/43.json deleted file mode 100644 index 1a97c63..0000000 --- a/assets/43.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 43", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/43.jpeg"} \ No newline at end of file diff --git a/assets/44.json b/assets/44.json deleted file mode 100644 index a4a7033..0000000 --- a/assets/44.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 44", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/44.jpeg"} \ No newline at end of file diff --git a/assets/45.json b/assets/45.json deleted file mode 100644 index dc15bf4..0000000 --- a/assets/45.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 45", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/45.jpeg"} \ No newline at end of file diff --git a/assets/46.json b/assets/46.json deleted file mode 100644 index e9f0a92..0000000 --- a/assets/46.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 46", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/46.jpeg"} \ No newline at end of file diff --git a/assets/47.json b/assets/47.json deleted file mode 100644 index 2dab2d2..0000000 --- a/assets/47.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 47", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/47.jpeg"} \ No newline at end of file diff --git a/assets/48.json b/assets/48.json deleted file mode 100644 index 8b9c398..0000000 --- a/assets/48.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 48", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/48.jpeg"} \ No newline at end of file diff --git a/assets/49.json b/assets/49.json deleted file mode 100644 index f513d0d..0000000 --- a/assets/49.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 49", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/49.jpeg"} \ No newline at end of file diff --git a/assets/5.json b/assets/5.json deleted file mode 100644 index e90eab6..0000000 --- a/assets/5.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 5", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/5.jpeg"} \ No newline at end of file diff --git a/assets/50.json b/assets/50.json deleted file mode 100644 index fd3c648..0000000 --- a/assets/50.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 50", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/50.jpeg"} \ No newline at end of file diff --git a/assets/51.json b/assets/51.json deleted file mode 100644 index 954906e..0000000 --- a/assets/51.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 51", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/51.jpeg"} \ No newline at end of file diff --git a/assets/52.json b/assets/52.json deleted file mode 100644 index 3f93c82..0000000 --- a/assets/52.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 52", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/52.jpeg"} \ No newline at end of file diff --git a/assets/53.json b/assets/53.json deleted file mode 100644 index 72d0ba3..0000000 --- a/assets/53.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 53", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/53.jpeg"} \ No newline at end of file diff --git a/assets/54.json b/assets/54.json deleted file mode 100644 index 6985713..0000000 --- a/assets/54.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 54", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/54.jpeg"} \ No newline at end of file diff --git a/assets/55.json b/assets/55.json deleted file mode 100644 index a246c79..0000000 --- a/assets/55.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 55", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/55.jpeg"} \ No newline at end of file diff --git a/assets/56.json b/assets/56.json deleted file mode 100644 index c82b803..0000000 --- a/assets/56.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 56", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/56.jpeg"} \ No newline at end of file diff --git a/assets/57.json b/assets/57.json deleted file mode 100644 index d2a4625..0000000 --- a/assets/57.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 57", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/57.jpeg"} \ No newline at end of file diff --git a/assets/58.json b/assets/58.json deleted file mode 100644 index 30202f0..0000000 --- a/assets/58.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 58", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/58.jpeg"} \ No newline at end of file diff --git a/assets/59.json b/assets/59.json deleted file mode 100644 index 271fe6a..0000000 --- a/assets/59.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 59", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/59.jpeg"} \ No newline at end of file diff --git a/assets/6.json b/assets/6.json deleted file mode 100644 index c85ac39..0000000 --- a/assets/6.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 6", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/6.jpeg"} \ No newline at end of file diff --git a/assets/60.json b/assets/60.json deleted file mode 100644 index 1e78e04..0000000 --- a/assets/60.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 60", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/60.jpeg"} \ No newline at end of file diff --git a/assets/61.json b/assets/61.json deleted file mode 100644 index f8d0794..0000000 --- a/assets/61.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 61", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/61.jpeg"} \ No newline at end of file diff --git a/assets/62.json b/assets/62.json deleted file mode 100644 index 04d90f5..0000000 --- a/assets/62.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 62", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/62.jpeg"} \ No newline at end of file diff --git a/assets/63.json b/assets/63.json deleted file mode 100644 index 2846eef..0000000 --- a/assets/63.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 63", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/63.jpeg"} \ No newline at end of file diff --git a/assets/64.json b/assets/64.json deleted file mode 100644 index a486ed4..0000000 --- a/assets/64.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 64", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/64.jpeg"} \ No newline at end of file diff --git a/assets/65.json b/assets/65.json deleted file mode 100644 index 107d500..0000000 --- a/assets/65.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 65", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/65.jpeg"} \ No newline at end of file diff --git a/assets/66.json b/assets/66.json deleted file mode 100644 index a3e51c8..0000000 --- a/assets/66.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 66", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/66.jpeg"} \ No newline at end of file diff --git a/assets/67.json b/assets/67.json deleted file mode 100644 index efc1576..0000000 --- a/assets/67.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 67", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/67.jpeg"} \ No newline at end of file diff --git a/assets/68.json b/assets/68.json deleted file mode 100644 index 6b22a5b..0000000 --- a/assets/68.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 68", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/68.jpeg"} \ No newline at end of file diff --git a/assets/69.json b/assets/69.json deleted file mode 100644 index e690b14..0000000 --- a/assets/69.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 69", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/69.jpeg"} \ No newline at end of file diff --git a/assets/7.json b/assets/7.json deleted file mode 100644 index 0a522bc..0000000 --- a/assets/7.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 7", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/7.jpeg"} \ No newline at end of file diff --git a/assets/70.json b/assets/70.json deleted file mode 100644 index d31374f..0000000 --- a/assets/70.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 70", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/70.jpeg"} \ No newline at end of file diff --git a/assets/71.json b/assets/71.json deleted file mode 100644 index 4abd4b2..0000000 --- a/assets/71.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 71", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/71.jpeg"} \ No newline at end of file diff --git a/assets/72.json b/assets/72.json deleted file mode 100644 index 20d9b0f..0000000 --- a/assets/72.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 72", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/72.jpeg"} \ No newline at end of file diff --git a/assets/73.json b/assets/73.json deleted file mode 100644 index 621f78b..0000000 --- a/assets/73.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 73", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/73.jpeg"} \ No newline at end of file diff --git a/assets/74.json b/assets/74.json deleted file mode 100644 index a869d14..0000000 --- a/assets/74.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 74", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/74.jpeg"} \ No newline at end of file diff --git a/assets/75.json b/assets/75.json deleted file mode 100644 index 7f16479..0000000 --- a/assets/75.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 75", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/75.jpeg"} \ No newline at end of file diff --git a/assets/76.json b/assets/76.json deleted file mode 100644 index 1a13487..0000000 --- a/assets/76.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 76", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/76.jpeg"} \ No newline at end of file diff --git a/assets/77.json b/assets/77.json deleted file mode 100644 index a6c39fc..0000000 --- a/assets/77.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 77", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/77.jpeg"} \ No newline at end of file diff --git a/assets/78.json b/assets/78.json deleted file mode 100644 index 1e4b57d..0000000 --- a/assets/78.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 78", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/78.jpeg"} \ No newline at end of file diff --git a/assets/79.json b/assets/79.json deleted file mode 100644 index 5af2e2f..0000000 --- a/assets/79.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 79", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/79.jpeg"} \ No newline at end of file diff --git a/assets/8.json b/assets/8.json deleted file mode 100644 index 02189f7..0000000 --- a/assets/8.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 8", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/8.jpeg"} \ No newline at end of file diff --git a/assets/80.json b/assets/80.json deleted file mode 100644 index e85565e..0000000 --- a/assets/80.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 80", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/80.jpeg"} \ No newline at end of file diff --git a/assets/81.json b/assets/81.json deleted file mode 100644 index 306067a..0000000 --- a/assets/81.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 81", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/81.jpeg"} \ No newline at end of file diff --git a/assets/82.json b/assets/82.json deleted file mode 100644 index 4028caf..0000000 --- a/assets/82.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 82", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/82.jpeg"} \ No newline at end of file diff --git a/assets/83.json b/assets/83.json deleted file mode 100644 index 6825a65..0000000 --- a/assets/83.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 83", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/83.jpeg"} \ No newline at end of file diff --git a/assets/84.json b/assets/84.json deleted file mode 100644 index db11e11..0000000 --- a/assets/84.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 84", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/84.jpeg"} \ No newline at end of file diff --git a/assets/85.json b/assets/85.json deleted file mode 100644 index c55919e..0000000 --- a/assets/85.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 85", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/85.jpeg"} \ No newline at end of file diff --git a/assets/86.json b/assets/86.json deleted file mode 100644 index af55e32..0000000 --- a/assets/86.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 86", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/86.jpeg"} \ No newline at end of file diff --git a/assets/87.json b/assets/87.json deleted file mode 100644 index 96d8891..0000000 --- a/assets/87.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 87", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/87.jpeg"} \ No newline at end of file diff --git a/assets/88.json b/assets/88.json deleted file mode 100644 index ca08dd8..0000000 --- a/assets/88.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 88", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/88.jpeg"} \ No newline at end of file diff --git a/assets/89.json b/assets/89.json deleted file mode 100644 index 6491e39..0000000 --- a/assets/89.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 89", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/89.jpeg"} \ No newline at end of file diff --git a/assets/9.json b/assets/9.json deleted file mode 100644 index 137d0a5..0000000 --- a/assets/9.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 9", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/9.jpeg"} \ No newline at end of file diff --git a/assets/90.json b/assets/90.json deleted file mode 100644 index 4aec2f9..0000000 --- a/assets/90.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 90", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/90.jpeg"} \ No newline at end of file diff --git a/assets/91.json b/assets/91.json deleted file mode 100644 index e5b2e13..0000000 --- a/assets/91.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 91", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/91.jpeg"} \ No newline at end of file diff --git a/assets/92.json b/assets/92.json deleted file mode 100644 index c2515b0..0000000 --- a/assets/92.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 92", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/92.jpeg"} \ No newline at end of file diff --git a/assets/93.json b/assets/93.json deleted file mode 100644 index 7d9b996..0000000 --- a/assets/93.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 93", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/93.jpeg"} \ No newline at end of file diff --git a/assets/94.json b/assets/94.json deleted file mode 100644 index 4d824e5..0000000 --- a/assets/94.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 94", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/94.jpeg"} \ No newline at end of file diff --git a/assets/95.json b/assets/95.json deleted file mode 100644 index c266e71..0000000 --- a/assets/95.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 95", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/95.jpeg"} \ No newline at end of file diff --git a/assets/96.json b/assets/96.json deleted file mode 100644 index 74509be..0000000 --- a/assets/96.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 96", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/96.jpeg"} \ No newline at end of file diff --git a/assets/97.json b/assets/97.json deleted file mode 100644 index f27efb5..0000000 --- a/assets/97.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 97", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/97.jpeg"} \ No newline at end of file diff --git a/assets/98.json b/assets/98.json deleted file mode 100644 index dc8bdbe..0000000 --- a/assets/98.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 98", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/98.jpeg"} \ No newline at end of file diff --git a/assets/99.json b/assets/99.json deleted file mode 100644 index 531c178..0000000 --- a/assets/99.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "Gan generated image 99", "image": "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/99.jpeg"} \ No newline at end of file diff --git a/contracts/Evaluator.cairo b/contracts/Evaluator.cairo deleted file mode 100644 index 245dc60..0000000 --- a/contracts/Evaluator.cairo +++ /dev/null @@ -1,779 +0,0 @@ -// ######## ERC 721 evaluator -// Soundtrack https://www.youtube.com/watch?v=iuWa5wh8lG0 - -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin, BitwiseBuiltin -from starkware.cairo.common.math import assert_not_zero - -from contracts.utils.ex00_base import ( - tderc20_address, - distribute_points, - ex_initializer, - has_validated_exercise, - validate_exercise, -) - -from contracts.token.ERC721.IERC721 import IERC721 -from contracts.token.ERC721.IERC721_metadata import IERC721_metadata -from contracts.IExerciseSolution import IExerciseSolution -from starkware.starknet.common.syscalls import get_contract_address, get_caller_address -from starkware.cairo.common.uint256 import ( - Uint256, - uint256_add, - uint256_sub, - uint256_le, - uint256_lt, - uint256_check, - uint256_eq, -) -from contracts.token.ERC20.ITDERC20 import ITDERC20 -from contracts.token.ERC20.IERC20 import IERC20 - -// -// Declaring storage vars -// Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity -// - -@storage_var -func has_been_paired(contract_address: felt) -> (has_been_paired: felt) { -} - -@storage_var -func player_exercise_solution_storage(player_address: felt) -> (contract_address: felt) { -} - -@storage_var -func assigned_rank_storage(player_address: felt) -> (rank: felt) { -} - -@storage_var -func next_rank_storage() -> (next_rank: felt) { -} - -@storage_var -func max_rank_storage() -> (max_rank: felt) { -} - -@storage_var -func random_attributes_storage(column: felt, rank: felt) -> (value: felt) { -} - -@storage_var -func was_initialized() -> (was_initialized: felt) { -} - -@storage_var -func dummy_token_address_storage() -> (dummy_token_address_storage: felt) { -} - -@storage_var -func dummy_metadata_erc721_storage() -> (dummy_metadata_erc721_storage: felt) { -} - -// -// Declaring getters -// Public variables should be declared explicitly with a getter -// - -@view -func player_exercise_solution{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - player_address: felt -) -> (contract_address: felt) { - let (contract_address) = player_exercise_solution_storage.read(player_address); - return (contract_address,); -} - -@view -func assigned_rank{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - player_address: felt -) -> (rank: felt) { - let (rank) = assigned_rank_storage.read(player_address); - return (rank,); -} - -@view -func assigned_legs_number{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - player_address: felt -) -> (legs: felt) { - let (rank) = assigned_rank(player_address); - let (legs) = random_attributes_storage.read(0, rank); - return (legs,); -} - -@view -func assigned_sex_number{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - player_address: felt -) -> (sex: felt) { - let (rank) = assigned_rank(player_address); - let (sex) = random_attributes_storage.read(1, rank); - return (sex,); -} - -@view -func assigned_wings_number{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - player_address: felt -) -> (wings: felt) { - let (rank) = assigned_rank(player_address); - let (wings) = random_attributes_storage.read(2, rank); - return (wings,); -} - -// ######## Constructor -// This function is called when the contract is deployed -// -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - _tderc20_address: felt, - _players_registry: felt, - _workshop_id: felt, - dummy_metadata_erc721_address: felt, - _dummy_token_address: felt, -) { - ex_initializer(_tderc20_address, _players_registry, _workshop_id); - dummy_token_address_storage.write(_dummy_token_address); - dummy_metadata_erc721_storage.write(dummy_metadata_erc721_address); - // Hard coded value for now - max_rank_storage.write(100); - return (); -} - -// ######## External functions -// These functions are callable by other contracts -// - -@external -func ex1_test_erc721{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - // Allocating locals. Make your code easier to write and read by avoiding some revoked references - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - let token_id: Uint256 = Uint256(1, 0); - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - - // Reading evaluator address - let (evaluator_address) = get_contract_address(); - // Reading who owns token 1 of exercise - let (token_1_owner_init) = IERC721.ownerOf( - contract_address=submited_exercise_address, token_id=token_id - ); - - with_attr error_message("Token 1 doesn't belong to the evaluator") { - // Verifying that token 1 belongs to evaluator - assert evaluator_address = token_1_owner_init; - } - // Reading balance of evaluator in exercise - let (evaluator_init_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=evaluator_address - ); - // Reading balance of msg sender in exercise - let (sender_init_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=sender_address - ); - - // Instanciating a zero in uint format - let zero_as_uint256: Uint256 = Uint256(0, 0); - let (is_equal) = uint256_eq(evaluator_init_balance, zero_as_uint256); - with_attr error_message("Evaluator's balance is 0") { - assert is_equal = 0; - } - - // Check that token 1 can be transferred back to msg.sender - with_attr error_message("Can't transfer the token 1") { - IERC721.transferFrom( - contract_address=submited_exercise_address, - _from=evaluator_address, - to=sender_address, - token_id=token_id, - ); - } - - // Reading balance of msg sender after transfer - let (sender_end_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=sender_address - ); - // Reading balance of evaluator after transfer - let (evaluator_end_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=evaluator_address - ); - // Reading who owns token 1 of exercise - let (token_1_owner_end) = IERC721.ownerOf( - contract_address=submited_exercise_address, token_id=token_id - ); - // Verifying that token 1 belongs to sender - with_attr error_message("Token 1 doesn't belong to the sender") { - assert token_1_owner_end = sender_address; - } - // I need value 1 in the uint format to be able to substract it, and add it, to compare balances - let one_as_uint256: Uint256 = Uint256(1, 0); - // Store expected balance in a variable, since I can't use everything on a single line - let evaluator_expected_balance: Uint256 = uint256_sub(evaluator_init_balance, one_as_uint256); - let (sender_expected_balance, _) = uint256_add(sender_init_balance, one_as_uint256); - // Verifying that balances where updated correctly - let (is_sender_balance_equal_to_expected) = uint256_eq( - sender_expected_balance, sender_end_balance - ); - with_attr error_message("Sender's balance wasn't updated") { - assert is_sender_balance_equal_to_expected = 1; - } - - let (is_evaluator_balance_equal_to_expected) = uint256_eq( - evaluator_expected_balance, evaluator_end_balance - ); - with_attr error_message("Evaluator's balance wasn't updated") { - assert is_evaluator_balance_equal_to_expected = 1; - } - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 1); - // This is necessary because of revoked references. Don't be scared, they won't stay around for too long... - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 1); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// Call this function to get assigned a rank, and the associate characteristics expected from your animal -@external -func ex2a_get_animal_rank{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - - // Reading caller address - let (sender_address) = get_caller_address(); - - ex2a_get_animal_rank_internal(sender_address); - - return (); -} - -// Show that you properly declared your animal -@external -func ex2b_test_declare_animal{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - - ex2b_test_declare_animal_internal(sender_address, token_id); - - return (); -} - -// Create a function that allows any breeder to call your contract and declare a new animal -@external -func ex3_declare_new_animal{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - // Reading evaluator address - let (evaluator_address) = get_contract_address(); - // Reading balance of evaluator in exercise - let (evaluator_init_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=evaluator_address - ); - // Requesting new attributes - ex2a_get_animal_rank_internal(sender_address); - - // Retrieve expected characteristics - let (expected_sex) = assigned_sex_number(sender_address); - let (expected_legs) = assigned_legs_number(sender_address); - let (expected_wings) = assigned_wings_number(sender_address); - - with_attr error_message("Couldn't declare a new animal") { - // Declaring a new animal with the desired parameters - let (created_token) = IExerciseSolution.declare_animal( - contract_address=submited_exercise_address, - sex=expected_sex, - legs=expected_legs, - wings=expected_wings, - ); - } - - // Checking that the animal was declared correctly. We basically reuse ex2 lol - // If it wasn't done correctly, this should fail - ex2b_test_declare_animal_internal(sender_address, created_token); - - // Ok so if I got until here then... nothing failed. I get points - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 3); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 3); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// Sometimes, animals die. Your contract should implement that. -@external -func ex4_declare_dead_animal{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - // Reading evaluator address - let (evaluator_address) = get_contract_address(); - // Getting initial token balance. Must be at least 1 - let (evaluator_init_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=evaluator_address - ); - - // Getting an animal id of Evaluator. tokenOfOwnerByIndex should return the list of NFTs owned by and address - with_attr error_message("Can't get the token owner by the index") { - let (token_id) = IExerciseSolution.token_of_owner_by_index( - contract_address=submited_exercise_address, account=evaluator_address, index=0 - ); - } - - with_attr error_message("Can't declare a dead animal") { - // Declaring it as dead - IExerciseSolution.declare_dead_animal( - contract_address=submited_exercise_address, token_id=token_id - ); - } - - // Checking end balance - let (evaluator_end_balance) = IERC721.balanceOf( - contract_address=submited_exercise_address, owner=evaluator_address - ); - // I need value 1 in the uint format to be able to substract it, and add it, to compare balances - let one_as_uint256: Uint256 = Uint256(1, 0); - // Store expected balance in a variable, since I can't use everything on a single line - let evaluator_expected_balance: Uint256 = uint256_sub(evaluator_init_balance, one_as_uint256); - // Verifying that balances where updated correctly - let (is_evaluator_balance_equal_to_expected) = uint256_eq( - evaluator_expected_balance, evaluator_end_balance - ); - with_attr error_message( - "The dead animal shouldn't count in the evaluator's balance (he should be burnt)") { - assert is_evaluator_balance_equal_to_expected = 1; - } - - with_attr error_message("Couldn't get the animal's characteristics") { - // Check that properties are deleted - // Reading animal characteristic in player solution - let (read_sex, read_legs, read_wings) = IExerciseSolution.get_animal_characteristics( - contract_address=submited_exercise_address, token_id=token_id - ); - } - - // Checking characteristics are correct - with_attr error_message("Dead animal's sex should be 0") { - assert read_sex = 0; - } - - with_attr error_message("Dead animal's legs should be 0") { - assert read_legs = 0; - } - - with_attr error_message("Dead animal's wings should be 0") { - assert read_wings = 0; - } - // TODO Testing killing another person's animal. The caller has to hold an animal - // Requires try / catch, or something smarter. I'll think about it. - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 4); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 4); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// For ex5 you need ERC20 tokens. Go get them -@external -func ex5a_i_have_dtk{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - // Reading sender balance in dummy token - let (dummy_token_address) = dummy_token_address_storage.read(); - let (dummy_token_init_balance) = IERC20.balanceOf( - contract_address=dummy_token_address, account=sender_address - ); - - // Verifying it's not 0 - // Instanciating a zero in uint format - let zero_as_uint256: Uint256 = Uint256(0, 0); - let (is_equal) = uint256_eq(dummy_token_init_balance, zero_as_uint256); - with_attr error_message("Caller should own some DTK") { - assert is_equal = 0; - } - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 51); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 51); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// Allow breeder to pay for registration as a breeder -@external -func ex5b_register_breeder{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - // Get evaluator address - let (evaluator_address) = get_contract_address(); - // Is evaluator currently a breeder? - let (is_evaluator_breeder_init) = IExerciseSolution.is_breeder( - contract_address=submited_exercise_address, account=evaluator_address - ); - with_attr error_message("Evaluator shouldn't be a breeder for now") { - assert is_evaluator_breeder_init = 0; - } - // TODO test that evaluator can not yet declare an animal (requires try/catch) - - // Reading registration price. Registration is payable in dummy token - with_attr error_message("Couldn't read the registration price") { - let (registration_price) = IExerciseSolution.registration_price( - contract_address=submited_exercise_address - ); - } - - // Reading evaluator balance in dummy token - let (dummy_token_address) = dummy_token_address_storage.read(); - let (dummy_token_init_balance) = IERC20.balanceOf( - contract_address=dummy_token_address, account=evaluator_address - ); - // Approve the exercise for spending my dummy tokens - IERC20.approve( - contract_address=dummy_token_address, - spender=submited_exercise_address, - amount=registration_price, - ); - - // Require breeder permission. - with_attr error_message("Couldn't register the Evaluator as a breeder") { - IExerciseSolution.register_me_as_breeder(contract_address=submited_exercise_address); - } - - with_attr error_message("Couldn't check that the evaluator is a breeder") { - // Check that I am indeed a breeder - let (is_evaluator_breeder_end) = IExerciseSolution.is_breeder( - contract_address=submited_exercise_address, account=evaluator_address - ); - } - with_attr error_message("Evaluator is not a breeder") { - assert is_evaluator_breeder_end = 1; - } - - // Check that my balance has been updated - let (dummy_token_end_balance) = IERC20.balanceOf( - contract_address=dummy_token_address, account=evaluator_address - ); - // Store expected balance in a variable, since I can't use everything on a single line - let evaluator_expected_balance: Uint256 = uint256_sub( - dummy_token_init_balance, registration_price - ); - // Verifying that balances where updated correctly - let (is_evaluator_balance_equal_to_expected) = uint256_eq( - evaluator_expected_balance, dummy_token_end_balance - ); - with_attr error_message( - "Actual registration cost is not the one returned by registration_price") { - assert is_evaluator_balance_equal_to_expected = 1; - } - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 52); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 52); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -@external -func ex6_claim_metadata_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) { - // Allocating locals. Make your code easier to write and read by avoiding some revoked references - alloc_locals; - // Retrieve dummy token address - let (dummy_metadata_erc721_address) = dummy_metadata_erc721_storage.read(); - // Reading caller address - let (sender_address) = get_caller_address(); - // Reading who owns token token_id - let (token_owner) = IERC721.ownerOf( - contract_address=dummy_metadata_erc721_address, token_id=token_id - ); - let token_id_low = token_id.low; - let token_id_high = token_id.high; - // Verifying that token 1 belongs to evaluator - with_attr error_message("Token {token_id_low}, {token_id_high} doesn't belong to you") { - assert sender_address = token_owner; - } - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 6); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 6); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// Check that ERC721 has implemented metadata queries -@external -func ex7_add_metadata{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - alloc_locals; - // Reading caller address - let (sender_address) = get_caller_address(); - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - // Get evaluator address - let (evaluator_address) = get_contract_address(); - // Retrieve dummy token address - let (dummy_metadata_erc721_address) = dummy_metadata_erc721_storage.read(); - // Reading metadata URI for token 1 on both contracts. For these to show up in Oasis, they should be equal - let token_id = Uint256(1, 0); - with_attr error_message("Couldn't retrieve the metadata URI") { - let (metadata_player_len, metadata_player) = IERC721_metadata.tokenURI( - contract_address=submited_exercise_address, token_id=token_id - ); - } - - let (metadata_dummy_len, metadata_dummy) = IERC721_metadata.tokenURI( - contract_address=dummy_metadata_erc721_address, token_id=token_id - ); - with_attr error_message("Your token uri is not the same length as the dummy metadata") { - // Verifying they are equal - assert metadata_dummy_len = metadata_player_len; - } - - with_attr error_message("Your token uri is not the same as the dummy metadata") { - ex7_check_arrays_are_equal(metadata_dummy_len, metadata_dummy, metadata_player); - } - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 7); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 7); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -@external -func submit_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - erc721_address: felt -) { - // Reading caller address - let (sender_address) = get_caller_address(); - // Checking this contract was not used by another group before - let (has_solution_been_submitted_before) = has_been_paired.read(erc721_address); - with_attr error_message("Solution already submited") { - assert has_solution_been_submitted_before = 0; - } - - // Assigning passed ERC721 as player ERC721 - player_exercise_solution_storage.write(sender_address, erc721_address); - has_been_paired.write(erc721_address, 1); - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 0); - // This is necessary because of revoked references. Don't be scared, they won't stay around for too long... - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 0); - // Sending points - - // Setup everything - distribute_points(sender_address, 2); - // Deploying contract points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -// -// Internal functions -// - -func ex2a_get_animal_rank_internal{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - sender_address: felt -) { - alloc_locals; - - // Reading next available slot - let (next_rank) = next_rank_storage.read(); - // Assigning to user - assigned_rank_storage.write(sender_address, next_rank); - - let new_next_rank = next_rank + 1; - let (max_rank) = max_rank_storage.read(); - - // Checking if we reach max_rank - if (new_next_rank == max_rank) { - next_rank_storage.write(0); - } else { - next_rank_storage.write(new_next_rank); - } - return (); -} - -func ex2b_test_declare_animal_internal{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(sender_address: felt, token_id: Uint256) { - alloc_locals; - // Retrieve expected characteristics - let (expected_sex) = assigned_sex_number(sender_address); - let (expected_legs) = assigned_legs_number(sender_address); - let (expected_wings) = assigned_wings_number(sender_address); - - // Retrieve exercise address - let (submited_exercise_address) = player_exercise_solution_storage.read(sender_address); - // Get current contract address - let (evaluator_address) = get_contract_address(); - // Reading who owns token 1 of exercise - let (token_owner) = IERC721.ownerOf( - contract_address=submited_exercise_address, token_id=token_id - ); - - with_attr error_message("Token 1 doesn't belong to the evaluator") { - // Verifying that token 1 belongs to evaluator - assert evaluator_address = token_owner; - } - - with_attr error_message("Couldn't retrieve the animal's characteristics") { - // Reading animal characteristic in player solution - let (read_sex, read_legs, read_wings) = IExerciseSolution.get_animal_characteristics( - contract_address=submited_exercise_address, token_id=token_id - ); - } - - // Checking characteristics are correct - with_attr error_message("Wrong sex number") { - assert read_sex = expected_sex; - } - with_attr error_message("Wrong legs number") { - assert read_legs = expected_legs; - } - with_attr error_message("Wrong wings number") { - assert read_wings = expected_wings; - } - - // Checking if player has validated this exercise before - let (has_validated) = has_validated_exercise(sender_address, 2); - - if (has_validated == 0) { - // player has validated - validate_exercise(sender_address, 2); - // Sending points - distribute_points(sender_address, 2); - return (); - } else { - return (); - } -} - -func ex7_check_arrays_are_equal{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - arrays_len: felt, array_1: felt*, array_2: felt* -) { - if (arrays_len == 0) { - return (); - } - ex7_check_arrays_are_equal(arrays_len=arrays_len - 1, array_1=array_1 + 1, array_2=array_2 + 1); - with_attr error_message("Arrays are not equal on cell {arrays_len}") { - assert [array_1] = [array_2]; - } - return (); -} -// -// External functions - Administration -// Only admins can call these. You don't need to understand them to finish the exercise. -// - -@external -func set_random_values{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - values_len: felt, values: felt*, column: felt -) { - // Check if the random values were already initialized - let (was_initialized_read) = was_initialized.read(); - with_attr error_message("Random values already initialized") { - assert was_initialized_read = 0; - } - - // Check that we fill max_ranK_storage cells - let (max_rank) = max_rank_storage.read(); - assert values_len = max_rank; - - // Storing passed values in the store - set_a_random_value(values_len, values, column); - - return (); -} - -@external -func finish_setup{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - // Check if the random values were already initialized - let (was_initialized_read) = was_initialized.read(); - with_attr error_message("Contract already initialized") { - assert was_initialized_read = 0; - } - // Mark that value store was initialized - was_initialized.write(1); - return (); -} - -func set_a_random_value{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - values_len: felt, values: felt*, column: felt -) { - if (values_len == 0) { - // Start with sum=0. - return (); - } - - set_a_random_value(values_len=values_len - 1, values=values + 1, column=column); - random_attributes_storage.write(column, values_len - 1, [values]); - - return (); -} diff --git a/contracts/IExerciseSolution.cairo b/contracts/IExerciseSolution.cairo deleted file mode 100644 index 50865ce..0000000 --- a/contracts/IExerciseSolution.cairo +++ /dev/null @@ -1,22 +0,0 @@ -%lang starknet - -from starkware.cairo.common.uint256 import Uint256 - -@contract_interface -namespace IExerciseSolution { - // Breeding function - func is_breeder(account: felt) -> (is_approved: felt) { - } - func registration_price() -> (price: Uint256) { - } - func register_me_as_breeder() -> (is_added: felt) { - } - func declare_animal(sex: felt, legs: felt, wings: felt) -> (token_id: Uint256) { - } - func get_animal_characteristics(token_id: Uint256) -> (sex: felt, legs: felt, wings: felt) { - } - func token_of_owner_by_index(account: felt, index: felt) -> (token_id: Uint256) { - } - func declare_dead_animal(token_id: Uint256) { - } -} diff --git a/contracts/token/ERC20/IERC20.cairo b/contracts/token/ERC20/IERC20.cairo deleted file mode 100644 index 92c633c..0000000 --- a/contracts/token/ERC20/IERC20.cairo +++ /dev/null @@ -1,33 +0,0 @@ -%lang starknet - -from starkware.cairo.common.uint256 import Uint256 - -@contract_interface -namespace IERC20 { - func name() -> (name: felt) { - } - - func symbol() -> (symbol: felt) { - } - - func decimals() -> (decimals: felt) { - } - - func totalSupply() -> (totalSupply: Uint256) { - } - - func balanceOf(account: felt) -> (balance: Uint256) { - } - - func allowance(owner: felt, spender: felt) -> (remaining: Uint256) { - } - - func transfer(recipient: felt, amount: Uint256) -> (success: felt) { - } - - func transferFrom(sender: felt, recipient: felt, amount: Uint256) -> (success: felt) { - } - - func approve(spender: felt, amount: Uint256) -> (success: felt) { - } -} diff --git a/contracts/token/ERC20/ITDERC20.cairo b/contracts/token/ERC20/ITDERC20.cairo deleted file mode 100644 index 3072ac8..0000000 --- a/contracts/token/ERC20/ITDERC20.cairo +++ /dev/null @@ -1,24 +0,0 @@ -%lang starknet -from starkware.cairo.common.uint256 import ( - Uint256, - uint256_add, - uint256_sub, - uint256_le, - uint256_lt, - uint256_check, -) -@contract_interface -namespace ITDERC20 { - func distribute_points(to: felt, amount: Uint256) { - } - func remove_points(to: felt, amount: Uint256) { - } - func set_teacher(account: felt, permission: felt) { - } - func is_teacher_or_exercise(account: felt) -> (permission: felt) { - } - func set_teachers_temp(accounts_len: felt, accounts: felt*) { - } - func set_teacher_temp(account: felt) { - } -} diff --git a/contracts/token/ERC20/TDERC20.cairo b/contracts/token/ERC20/TDERC20.cairo deleted file mode 100644 index 5b89ba2..0000000 --- a/contracts/token/ERC20/TDERC20.cairo +++ /dev/null @@ -1,222 +0,0 @@ -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin -from starkware.cairo.common.uint256 import Uint256 -from starkware.starknet.common.syscalls import get_caller_address - -from openzeppelin.token.erc20.library import ERC20 - -@storage_var -func teachers_and_exercises_accounts(account: felt) -> (balance: felt) { -} - -@storage_var -func is_transferable_storage() -> (is_transferable_storage: felt) { -} - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - name: felt, symbol: felt, initial_supply: Uint256, recipient: felt, owner: felt -) { - ERC20.initializer(name, symbol, 18); - ERC20._mint(recipient, initial_supply); - teachers_and_exercises_accounts.write(owner, 1); - return (); -} - -// -// Getters -// - -@view -func is_transferable{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - is_transferable: felt -) { - let (is_transferable) = is_transferable_storage.read(); - return (is_transferable,); -} - -@view -func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { - let (name) = ERC20.name(); - return (name,); -} - -@view -func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { - let (symbol) = ERC20.symbol(); - return (symbol,); -} - -@view -func totalSupply{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - totalSupply: Uint256 -) { - let (totalSupply: Uint256) = ERC20.total_supply(); - return (totalSupply,); -} - -@view -func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - decimals: felt -) { - let (decimals) = ERC20.decimals(); - return (decimals,); -} - -@view -func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(account: felt) -> ( - balance: Uint256 -) { - let (balance: Uint256) = ERC20.balance_of(account); - return (balance,); -} - -@view -func allowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - owner: felt, spender: felt -) -> (remaining: Uint256) { - let (remaining: Uint256) = ERC20.allowance(owner, spender); - return (remaining,); -} - -// -// Externals -// - -@external -func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - recipient: felt, amount: Uint256 -) -> (success: felt) { - _is_transferable(); - ERC20.transfer(recipient, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func transferFrom{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - sender: felt, recipient: felt, amount: Uint256 -) -> (success: felt) { - _is_transferable(); - ERC20.transfer_from(sender, recipient, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func approve{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, amount: Uint256 -) -> (success: felt) { - ERC20.approve(spender, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func increaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, added_value: Uint256 -) -> (success: felt) { - ERC20.increase_allowance(spender, added_value); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func decreaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, subtracted_value: Uint256 -) -> (success: felt) { - ERC20.decrease_allowance(spender, subtracted_value); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func distribute_points{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - to: felt, amount: Uint256 -) { - only_teacher_or_exercise(); - ERC20._mint(to, amount); - return (); -} - -@external -func remove_points{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - to: felt, amount: Uint256 -) { - only_teacher_or_exercise(); - ERC20._burn(to, amount); - return (); -} - -@external -func set_teacher{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, permission: felt -) { - only_teacher_or_exercise(); - teachers_and_exercises_accounts.write(account, permission); - - return (); -} - -@external -func set_teachers{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - accounts_len: felt, accounts: felt* -) { - only_teacher_or_exercise(); - _set_teacher(accounts_len, accounts); - return (); -} - -@external -func set_transferable{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - permission: felt -) { - only_teacher_or_exercise(); - _set_transferable(permission); - return (); -} - -@view -func is_teacher_or_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt -) -> (permission: felt) { - let (permission: felt) = teachers_and_exercises_accounts.read(account); - return (permission,); -} - -func _set_teacher{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - accounts_len: felt, accounts: felt* -) { - if (accounts_len == 0) { - // Start with sum=0. - return (); - } - - // If length is NOT zero, then the function calls itself again, by moving forward one slot - _set_teacher(accounts_len=accounts_len - 1, accounts=accounts + 1); - - // This part of the function is first reached when length=0. - teachers_and_exercises_accounts.write([accounts], 1); - return (); -} - -func only_teacher_or_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - let (caller) = get_caller_address(); - let (permission) = teachers_and_exercises_accounts.read(account=caller); - assert permission = 1; - return (); -} - -func _is_transferable{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - let (permission) = is_transferable_storage.read(); - assert permission = 1; - return (); -} - -func _set_transferable{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - permission: felt -) { - is_transferable_storage.write(permission); - return (); -} diff --git a/contracts/token/ERC20/dummy_token.cairo b/contracts/token/ERC20/dummy_token.cairo deleted file mode 100644 index 7c79c0a..0000000 --- a/contracts/token/ERC20/dummy_token.cairo +++ /dev/null @@ -1,122 +0,0 @@ -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin -from starkware.cairo.common.uint256 import Uint256 -from starkware.starknet.common.syscalls import get_caller_address - -from openzeppelin.token.erc20.library import ERC20 - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - name: felt, symbol: felt, initial_supply: Uint256, recipient: felt -) { - ERC20.initializer(name, symbol, 18); - ERC20._mint(recipient, initial_supply); - return (); -} - -// -// Getters -// - -@view -func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { - let (name) = ERC20.name(); - return (name,); -} - -@view -func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { - let (symbol) = ERC20.symbol(); - return (symbol,); -} - -@view -func totalSupply{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - totalSupply: Uint256 -) { - let (totalSupply: Uint256) = ERC20.total_supply(); - return (totalSupply,); -} - -@view -func decimals{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - decimals: felt -) { - let (decimals) = ERC20.decimals(); - return (decimals,); -} - -@view -func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(account: felt) -> ( - balance: Uint256 -) { - let (balance: Uint256) = ERC20.balance_of(account); - return (balance,); -} - -@view -func allowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - owner: felt, spender: felt -) -> (remaining: Uint256) { - let (remaining: Uint256) = ERC20.allowance(owner, spender); - return (remaining,); -} - -// -// Externals -// - -@external -func faucet{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (success: felt) { - let amount: Uint256 = Uint256(100 * 1000000000000000000, 0); - let (caller) = get_caller_address(); - ERC20._mint(caller, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func transfer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - recipient: felt, amount: Uint256 -) -> (success: felt) { - ERC20.transfer(recipient, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func transferFrom{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - sender: felt, recipient: felt, amount: Uint256 -) -> (success: felt) { - ERC20.transfer_from(sender, recipient, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func approve{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, amount: Uint256 -) -> (success: felt) { - ERC20.approve(spender, amount); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func increaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, added_value: Uint256 -) -> (success: felt) { - ERC20.increase_allowance(spender, added_value); - // Cairo equivalent to 'return (true)' - return (1,); -} - -@external -func decreaseAllowance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - spender: felt, subtracted_value: Uint256 -) -> (success: felt) { - ERC20.decrease_allowance(spender, subtracted_value); - // Cairo equivalent to 'return (true)' - return (1,); -} diff --git a/contracts/token/ERC721/ERC721.cairo b/contracts/token/ERC721/ERC721.cairo deleted file mode 100644 index 29fee30..0000000 --- a/contracts/token/ERC721/ERC721.cairo +++ /dev/null @@ -1,105 +0,0 @@ -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin -from starkware.cairo.common.uint256 import Uint256 - -from openzeppelin.token.erc721.library import ERC721 - -// -// Constructor -// - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - name: felt, symbol: felt, to_: felt -) { - ERC721.initializer(name, symbol); - let to = to_; - let token_id: Uint256 = Uint256(1, 0); - ERC721._mint(to, token_id); - return (); -} - -// -// Getters -// - -@view -func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { - let (name) = ERC721.name(); - return (name,); -} - -@view -func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { - let (symbol) = ERC721.symbol(); - return (symbol,); -} - -@view -func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) -> ( - balance: Uint256 -) { - let (balance: Uint256) = ERC721.balance_of(owner); - return (balance,); -} - -@view -func ownerOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (owner: felt) { - let (owner: felt) = ERC721.owner_of(token_id); - return (owner,); -} - -@view -func getApproved{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (approved: felt) { - let (approved: felt) = ERC721.get_approved(token_id); - return (approved,); -} - -@view -func isApprovedForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - owner: felt, operator: felt -) -> (is_approved: felt) { - let (is_approved: felt) = ERC721.is_approved_for_all(owner, operator); - return (is_approved,); -} - -// -// Externals -// - -@external -func approve{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - to: felt, token_id: Uint256 -) { - ERC721.approve(to, token_id); - return (); -} - -@external -func setApprovalForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - operator: felt, approved: felt -) { - ERC721.set_approval_for_all(operator, approved); - return (); -} - -@external -func transferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256 -) { - ERC721.transfer_from(_from, to, token_id); - return (); -} - -@external -func safeTransferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256, data_len: felt, data: felt* -) { - ERC721.safe_transfer_from(_from, to, token_id, data_len, data); - return (); -} diff --git a/contracts/token/ERC721/ERC721_Metadata_base.cairo b/contracts/token/ERC721/ERC721_Metadata_base.cairo deleted file mode 100644 index de4b543..0000000 --- a/contracts/token/ERC721/ERC721_Metadata_base.cairo +++ /dev/null @@ -1,98 +0,0 @@ -%lang starknet - -from starkware.cairo.common.alloc import alloc -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin -from starkware.cairo.common.uint256 import Uint256 - -from openzeppelin.token.erc721.library import ERC721 - -from openzeppelin.introspection.erc165.library import ERC165 - -from contracts.utils.ShortString import uint256_to_ss -from contracts.utils.Array import concat_arr - -// -// Storage -// - -@storage_var -func ERC721_base_token_uri(index: felt) -> (res: felt) { -} - -@storage_var -func ERC721_base_token_uri_len() -> (res: felt) { -} - -@storage_var -func ERC721_base_token_uri_suffix() -> (res: felt) { -} - -// -// Constructor -// - -func ERC721_Metadata_initializer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - ) { - // register IERC721_Metadata - ERC165.register_interface(0x5b5e139f); - return (); -} - -func ERC721_Metadata_tokenURI{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (token_uri_len: felt, token_uri: felt*) { - alloc_locals; - - let exists = ERC721._exists(token_id); - assert exists = 1; - - let (local base_token_uri) = alloc(); - let (local base_token_uri_len) = ERC721_base_token_uri_len.read(); - - _ERC721_Metadata_baseTokenURI(base_token_uri_len, base_token_uri); - - let (token_id_ss_len, token_id_ss) = uint256_to_ss(token_id); - let (token_uri_temp, token_uri_len_temp) = concat_arr( - base_token_uri_len, base_token_uri, token_id_ss_len, token_id_ss - ); - let (ERC721_base_token_uri_suffix_local) = ERC721_base_token_uri_suffix.read(); - let (local suffix) = alloc(); - [suffix] = ERC721_base_token_uri_suffix_local; - let (token_uri, token_uri_len) = concat_arr(token_uri_len_temp, token_uri_temp, 1, suffix); - - return (token_uri_len=token_uri_len, token_uri=token_uri); -} - -func _ERC721_Metadata_baseTokenURI{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - base_token_uri_len: felt, base_token_uri: felt* -) { - if (base_token_uri_len == 0) { - return (); - } - let (base) = ERC721_base_token_uri.read(base_token_uri_len); - assert [base_token_uri] = base; - _ERC721_Metadata_baseTokenURI( - base_token_uri_len=base_token_uri_len - 1, base_token_uri=base_token_uri + 1 - ); - return (); -} - -func ERC721_Metadata_setBaseTokenURI{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(token_uri_len: felt, token_uri: felt*, token_uri_suffix: felt) { - _ERC721_Metadata_setBaseTokenURI(token_uri_len, token_uri); - ERC721_base_token_uri_len.write(token_uri_len); - ERC721_base_token_uri_suffix.write(token_uri_suffix); - return (); -} - -func _ERC721_Metadata_setBaseTokenURI{ - syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(token_uri_len: felt, token_uri: felt*) { - if (token_uri_len == 0) { - return (); - } - ERC721_base_token_uri.write(index=token_uri_len, value=[token_uri]); - _ERC721_Metadata_setBaseTokenURI(token_uri_len=token_uri_len - 1, token_uri=token_uri + 1); - return (); -} diff --git a/contracts/token/ERC721/ERC721_metadata.cairo b/contracts/token/ERC721/ERC721_metadata.cairo deleted file mode 100644 index 8b2e4c4..0000000 --- a/contracts/token/ERC721/ERC721_metadata.cairo +++ /dev/null @@ -1,174 +0,0 @@ -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin -from starkware.cairo.common.uint256 import Uint256 - -from openzeppelin.token.erc721.library import ERC721 -from openzeppelin.introspection.erc165.library import ERC165 -from openzeppelin.access.ownable.library import Ownable - -from contracts.token.ERC721.ERC721_Metadata_base import ( - ERC721_Metadata_initializer, - ERC721_Metadata_tokenURI, - ERC721_Metadata_setBaseTokenURI, -) - -// -// Constructor -// - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - name: felt, - symbol: felt, - owner: felt, - base_token_uri_len: felt, - base_token_uri: felt*, - token_uri_suffix: felt, -) { - ERC721.initializer(name, symbol); - ERC721_Metadata_initializer(); - Ownable.initializer(owner); - ERC721_Metadata_setBaseTokenURI(base_token_uri_len, base_token_uri, token_uri_suffix); - return (); -} - -// -// Getters -// - -@view -func getOwner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (owner: felt) { - let (owner) = Ownable.owner(); - return (owner=owner); -} - -@view -func supportsInterface{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - interface_id: felt -) -> (success: felt) { - let (success) = ERC165.supports_interface(interface_id); - return (success,); -} - -@view -func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { - let (name) = ERC721.name(); - return (name,); -} - -@view -func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { - let (symbol) = ERC721.symbol(); - return (symbol,); -} - -@view -func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) -> ( - balance: Uint256 -) { - let (balance: Uint256) = ERC721.balance_of(owner); - return (balance,); -} - -@view -func ownerOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (owner: felt) { - let (owner: felt) = ERC721.owner_of(token_id); - return (owner,); -} - -@view -func getApproved{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (approved: felt) { - let (approved: felt) = ERC721.get_approved(token_id); - return (approved,); -} - -@view -func isApprovedForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - owner: felt, operator: felt -) -> (is_approved: felt) { - let (is_approved: felt) = ERC721.is_approved_for_all(owner, operator); - return (is_approved,); -} - -@view -func tokenURI{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (token_uri_len: felt, token_uri: felt*) { - let (token_uri_len, token_uri) = ERC721_Metadata_tokenURI(token_id); - return (token_uri_len=token_uri_len, token_uri=token_uri); -} - -// -// Externals -// - -@external -func approve{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - to: felt, token_id: Uint256 -) { - ERC721.approve(to, token_id); - return (); -} - -@external -func setApprovalForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - operator: felt, approved: felt -) { - ERC721.set_approval_for_all(operator, approved); - return (); -} - -@external -func transferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256 -) { - ERC721.transfer_from(_from, to, token_id); - return (); -} - -@external -func safeTransferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256, data_len: felt, data: felt* -) { - ERC721.safe_transfer_from(_from, to, token_id, data_len, data); - return (); -} - -@external -func setTokenURI{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - base_token_uri_len: felt, base_token_uri: felt*, token_uri_suffix: felt -) { - Ownable.assert_only_owner(); - ERC721_Metadata_setBaseTokenURI(base_token_uri_len, base_token_uri, token_uri_suffix); - return (); -} - -@external -func mint{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - to: felt, token_id: Uint256 -) { - Ownable.assert_only_owner(); - ERC721._mint(to, token_id); - return (); -} - -@external -func burn{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}(token_id: Uint256) { - Ownable.assert_only_owner(); - ERC721._burn(token_id); - return (); -} - -@external -func transferOwnership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - new_owner: felt -) -> (new_owner: felt) { - // Ownership check is handled by this function - Ownable.transfer_ownership(new_owner); - return (new_owner=new_owner); -} diff --git a/contracts/token/ERC721/IERC721.cairo b/contracts/token/ERC721/IERC721.cairo deleted file mode 100644 index 2a5b735..0000000 --- a/contracts/token/ERC721/IERC721.cairo +++ /dev/null @@ -1,30 +0,0 @@ -%lang starknet - -from starkware.cairo.common.uint256 import Uint256 - -@contract_interface -namespace IERC721 { - func balanceOf(owner: felt) -> (balance: Uint256) { - } - - func ownerOf(token_id: Uint256) -> (owner: felt) { - } - - func safeTransferFrom(_from: felt, to: felt, token_id: Uint256, data_len: felt, data: felt*) { - } - - func transferFrom(_from: felt, to: felt, token_id: Uint256) { - } - - func approve(approved: felt, token_id: Uint256) { - } - - func setApprovalForAll(operator: felt, approved: felt) { - } - - func getApproved(token_id: Uint256) -> (approved: felt) { - } - - func isApprovedForAll(owner: felt, operator: felt) -> (is_approved: felt) { - } -} diff --git a/contracts/token/ERC721/IERC721_Receiver.cairo b/contracts/token/ERC721/IERC721_Receiver.cairo deleted file mode 100644 index add8bf4..0000000 --- a/contracts/token/ERC721/IERC721_Receiver.cairo +++ /dev/null @@ -1,11 +0,0 @@ -%lang starknet - -from starkware.cairo.common.uint256 import Uint256 - -@contract_interface -namespace IERC721_Receiver { - func onERC721Received( - operator: felt, _from: felt, token_id: Uint256, data_len: felt, data: felt* - ) -> (selector: felt) { - } -} diff --git a/contracts/token/ERC721/IERC721_metadata.cairo b/contracts/token/ERC721/IERC721_metadata.cairo deleted file mode 100644 index 1b448d4..0000000 --- a/contracts/token/ERC721/IERC721_metadata.cairo +++ /dev/null @@ -1,33 +0,0 @@ -%lang starknet - -from starkware.cairo.common.uint256 import Uint256 - -@contract_interface -namespace IERC721_metadata { - func balanceOf(owner: felt) -> (balance: Uint256) { - } - - func ownerOf(token_id: Uint256) -> (owner: felt) { - } - - func safeTransferFrom(_from: felt, to: felt, token_id: Uint256, data_len: felt, data: felt*) { - } - - func transferFrom(_from: felt, to: felt, token_id: Uint256) { - } - - func approve(approved: felt, token_id: Uint256) { - } - - func setApprovalForAll(operator: felt, approved: felt) { - } - - func getApproved(token_id: Uint256) -> (approved: felt) { - } - - func isApprovedForAll(owner: felt, operator: felt) -> (is_approved: felt) { - } - - func tokenURI(token_id: Uint256) -> (token_uri_len: felt, token_uri: felt*) { - } -} diff --git a/contracts/token/ERC721/TDERC721_metadata.cairo b/contracts/token/ERC721/TDERC721_metadata.cairo deleted file mode 100644 index ffd2236..0000000 --- a/contracts/token/ERC721/TDERC721_metadata.cairo +++ /dev/null @@ -1,209 +0,0 @@ -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin -from starkware.cairo.common.uint256 import ( - Uint256, - uint256_add, - uint256_sub, - uint256_le, - uint256_lt, - uint256_check, - uint256_eq, -) -from openzeppelin.token.erc721.library import ERC721 -from openzeppelin.introspection.erc165.library import ERC165 -from openzeppelin.access.ownable.library import Ownable - -from contracts.token.ERC721.ERC721_Metadata_base import ( - ERC721_Metadata_initializer, - ERC721_Metadata_tokenURI, - ERC721_Metadata_setBaseTokenURI, -) - -// -// Constructor -// - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - name: felt, - symbol: felt, - owner: felt, - base_token_uri_len: felt, - base_token_uri: felt*, - token_uri_suffix: felt, -) { - ERC721.initializer(name, symbol); - ERC721_Metadata_initializer(); - Ownable.initializer(owner); - ERC721_Metadata_setBaseTokenURI(base_token_uri_len, base_token_uri, token_uri_suffix); - let one_as_uint = Uint256(1, 0); - next_token_id_storage.write(one_as_uint); - return (); -} - -// -// Storage vars -// - -@storage_var -func next_token_id_storage() -> (next_token_id: Uint256) { -} - -// -// Getters -// - -@view -func next_token_id{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - next_token_id: Uint256 -) { - let (next_token_id) = next_token_id_storage.read(); - return (next_token_id=next_token_id); -} - -@view -func getOwner{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (owner: felt) { - let (owner) = Ownable.owner(); - return (owner=owner); -} - -@view -func supportsInterface{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - interface_id: felt -) -> (success: felt) { - let (success) = ERC165.supports_interface(interface_id); - return (success,); -} - -@view -func name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (name: felt) { - let (name) = ERC721.name(); - return (name,); -} - -@view -func symbol{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> (symbol: felt) { - let (symbol) = ERC721.symbol(); - return (symbol,); -} - -@view -func balanceOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(owner: felt) -> ( - balance: Uint256 -) { - let (balance: Uint256) = ERC721.balance_of(owner); - return (balance,); -} - -@view -func ownerOf{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (owner: felt) { - let (owner: felt) = ERC721.owner_of(token_id); - return (owner,); -} - -@view -func getApproved{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (approved: felt) { - let (approved: felt) = ERC721.get_approved(token_id); - return (approved,); -} - -@view -func isApprovedForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - owner: felt, operator: felt -) -> (is_approved: felt) { - let (is_approved: felt) = ERC721.is_approved_for_all(owner, operator); - return (is_approved,); -} - -@view -func tokenURI{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - token_id: Uint256 -) -> (token_uri_len: felt, token_uri: felt*) { - let (token_uri_len, token_uri) = ERC721_Metadata_tokenURI(token_id); - return (token_uri_len=token_uri_len, token_uri=token_uri); -} - -// -// Externals -// - -@external -func approve{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - to: felt, token_id: Uint256 -) { - ERC721.approve(to, token_id); - return (); -} - -@external -func setApprovalForAll{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - operator: felt, approved: felt -) { - ERC721.set_approval_for_all(operator, approved); - return (); -} - -@external -func transferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256 -) { - ERC721.transfer_from(_from, to, token_id); - return (); -} - -@external -func safeTransferFrom{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - _from: felt, to: felt, token_id: Uint256, data_len: felt, data: felt* -) { - ERC721.safe_transfer_from(_from, to, token_id, data_len, data); - return (); -} - -@external -func setTokenURI{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - base_token_uri_len: felt, base_token_uri: felt*, token_uri_suffix: felt -) { - Ownable.assert_only_owner(); - ERC721_Metadata_setBaseTokenURI(base_token_uri_len, base_token_uri, token_uri_suffix); - return (); -} - -@external -func mint{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}( - to: felt, token_id: Uint256 -) { - Ownable.assert_only_owner(); - ERC721._mint(to, token_id); - return (); -} - -@external -func claim{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}(to: felt) { - let (token_id) = next_token_id_storage.read(); - let one_as_uint = Uint256(1, 0); - let (next_token_id, _) = uint256_add(one_as_uint, token_id); - next_token_id_storage.write(next_token_id); - ERC721._mint(to, token_id); - return (); -} - -@external -func burn{pedersen_ptr: HashBuiltin*, syscall_ptr: felt*, range_check_ptr}(token_id: Uint256) { - Ownable.assert_only_owner(); - ERC721._burn(token_id); - return (); -} - -@external -func transferOwnership{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - new_owner: felt -) -> (new_owner: felt) { - // Ownership check is handled by this function - Ownable.transfer_ownership(new_owner); - return (new_owner=new_owner); -} diff --git a/contracts/utils/Array.cairo b/contracts/utils/Array.cairo deleted file mode 100644 index c766b3a..0000000 --- a/contracts/utils/Array.cairo +++ /dev/null @@ -1,14 +0,0 @@ -// https://github.com/marcellobardus/starknet-l2-storage-verifier/blob/master/contracts/starknet/lib/concat_arr.cairo - -from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.alloc import alloc - -func concat_arr{range_check_ptr}(arr1_len: felt, arr1: felt*, arr2_len: felt, arr2: felt*) -> ( - res: felt*, res_len: felt -) { - alloc_locals; - let (local res: felt*) = alloc(); - memcpy(res, arr1, arr1_len); - memcpy(res + arr1_len, arr2, arr2_len); - return (res, arr1_len + arr2_len); -} diff --git a/contracts/utils/Array_sekai.cairo b/contracts/utils/Array_sekai.cairo deleted file mode 100644 index d1594ba..0000000 --- a/contracts/utils/Array_sekai.cairo +++ /dev/null @@ -1,16 +0,0 @@ -// https://github.com/marcellobardus/starknet-l2-storage-verifier/blob/master/contracts/starknet/lib/concat_arr.cairo - -// # Edit for return values in easier order - -from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.alloc import alloc - -func concat_arr{range_check_ptr}(arr1_len: felt, arr1: felt*, arr2_len: felt, arr2: felt*) -> ( - res_len: felt, res: felt* -) { - alloc_locals; - let (local res: felt*) = alloc(); - memcpy(res, arr1, arr1_len); - memcpy(res + arr1_len, arr2, arr2_len); - return (arr1_len + arr2_len, res); -} diff --git a/contracts/utils/Iplayers_registry.cairo b/contracts/utils/Iplayers_registry.cairo deleted file mode 100644 index 58ec511..0000000 --- a/contracts/utils/Iplayers_registry.cairo +++ /dev/null @@ -1,27 +0,0 @@ -%lang starknet - -//################### -// INTERFACE -//################### - -@contract_interface -namespace Iplayers_registry { - func has_validated_exercise(account: felt, workshop: felt, exercise: felt) -> ( - has_validated_exercise: felt - ) { - } - func is_exercise_or_admin(account: felt) -> (permission: felt) { - } - func next_player_rank() -> (next_player_rank: felt) { - } - func players_registry(rank: felt) -> (account: felt) { - } - func player_ranks(account: felt) -> (rank: felt) { - } - func set_exercise_or_admin(account: felt, permission: felt) { - } - func set_exercises_or_admins(accounts_len: felt, accounts: felt*) { - } - func validate_exercise(account: felt, workshop: felt, exercise: felt) { - } -} diff --git a/contracts/utils/ShortString.cairo b/contracts/utils/ShortString.cairo deleted file mode 100644 index 1e6a399..0000000 --- a/contracts/utils/ShortString.cairo +++ /dev/null @@ -1,141 +0,0 @@ -%lang starknet - -from starkware.cairo.common.alloc import alloc -from starkware.cairo.common.uint256 import Uint256, uint256_unsigned_div_rem, uint256_eq -from starkware.cairo.common.math import unsigned_div_rem -from starkware.cairo.common.pow import pow - -// -// Converts a felt it's equivalent short string. In the case where the felt length exceeds -// the maximum short string length (31 bytes), the remainder will be returned -// - eg. felt(10) -> '10', 0 -// - eg. felt(123 "8*31") -> '8'*31, 123 -// -func felt_to_ss_partial{range_check_ptr}(input: felt) -> (running_total: felt, remainder: felt) { - let (running_total, remainder) = _felt_to_ss_partial(input, 0); - return (running_total=running_total, remainder=remainder); -} - -func _felt_to_ss_partial{range_check_ptr}(val: felt, depth: felt) -> ( - running_total: felt, remainder: felt -) { - alloc_locals; - - // Used to shift the word by depth - let (local word_exponent) = pow(2, 8 * depth); - - let (q, r) = unsigned_div_rem(val, 10); - if (q == 0) { - let res = word_exponent * (r + 48); - return (running_total=res, remainder=q); - } - if (depth == 30) { - let res = word_exponent * (r + 48); - return (running_total=res, remainder=q); - } - - let depth = depth + 1; - let (running_total, remainder) = _felt_to_ss_partial(q, depth); - let res = word_exponent * (r + 48) + running_total; - return (running_total=res, remainder=remainder); -} - -// -// Converts a felt to it's equivalent in a list of felts -// - eg. felt(123 "8"*31) -> 123, '8'*31 -// -func felt_to_ss{range_check_ptr}(input: felt) -> (res_len: felt, res: felt*) { - alloc_locals; - - let (local res) = alloc(); - - if (input == 0) { - assert res[0] = 48; - return (res_len=1, res=res); - } - - let (res_len) = _felt_to_ss(input, res); - return (res_len=res_len, res=res); -} - -func _felt_to_ss{range_check_ptr}(val: felt, res: felt*) -> (res_len: felt) { - alloc_locals; - if (val == 0) { - return (res_len=0); - } - - let (local running_total, remainder) = felt_to_ss_partial(val); - let (res_len) = _felt_to_ss(remainder, res); - assert res[res_len] = running_total; - return (res_len=res_len + 1); -} - -// -// Converts a uint it's equivalent short string. In the case where the felt length exceeds -// the maximum short string length (31 bytes), the remainder will be returned -// - eg. felt(10) -> '10', 0 -// - eg. felt(123 "8*31") -> '8'*31, 123 -// -func uint256_to_ss_partial{range_check_ptr}(input: Uint256) -> ( - running_total: felt, remainder: Uint256 -) { - let (running_total, remainder) = _uint256_to_ss_partial(input, 0); - return (running_total=running_total, remainder=remainder); -} - -func _uint256_to_ss_partial{range_check_ptr}(val: Uint256, depth: felt) -> ( - running_total: felt, remainder: Uint256 -) { - alloc_locals; - - // Used to shift the word by depth - let (local word_exponent) = pow(2, 8 * depth); - - let (q, r) = uint256_unsigned_div_rem(val, Uint256(10, 0)); - let (quotient_eq) = uint256_eq(q, Uint256(0, 0)); - if (quotient_eq == 1) { - let res = word_exponent * (r.low + 48); - return (running_total=res, remainder=q); - } - if (depth == 30) { - let res = word_exponent * (r.low + 48); - return (running_total=res, remainder=q); - } - - let depth = depth + 1; - let (running_total, remainder) = _uint256_to_ss_partial(q, depth); - let res = word_exponent * (r.low + 48) + running_total; - return (running_total=res, remainder=remainder); -} - -// -// Converts a uint256 to it's equivalent in a list of felts -// -func uint256_to_ss{range_check_ptr}(input: Uint256) -> (res_len: felt, res: felt*) { - alloc_locals; - - let (local res) = alloc(); - - let (input_eq) = uint256_eq(input, Uint256(0, 0)); - if (input_eq == 1) { - assert res[0] = 48; - return (res_len=1, res=res); - } - - let (res_len) = _uint256_to_ss(input, res); - return (res_len=res_len, res=res); -} - -func _uint256_to_ss{range_check_ptr}(val: Uint256, res: felt*) -> (res_len: felt) { - alloc_locals; - - let (val_eq) = uint256_eq(val, Uint256(0, 0)); - if (val_eq == 1) { - return (res_len=0); - } - - let (local running_total, remainder) = uint256_to_ss_partial(val); - let (res_len) = _uint256_to_ss(remainder, res); - assert res[res_len] = running_total; - return (res_len=res_len + 1); -} diff --git a/contracts/utils/String.cairo b/contracts/utils/String.cairo deleted file mode 100644 index a710bb6..0000000 --- a/contracts/utils/String.cairo +++ /dev/null @@ -1,295 +0,0 @@ -%lang starknet - -from starkware.cairo.common.alloc import alloc -from starkware.cairo.common.bitwise import bitwise_and -from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, HashBuiltin -from starkware.cairo.common.math import unsigned_div_rem, assert_le, assert_250_bit -from starkware.cairo.common.math_cmp import is_le -from starkware.cairo.common.pow import pow - -from contracts.utils.Array_sekai import concat_arr - -const SHORT_STRING_MAX_LEN = 31; // The maximum character length of a short string -const SHORT_STRING_MAX_VALUE = 2 ** 248 - 1; // The maximum value for a short string of 31 characters (= 0b11...11 = 0xff...ff) -const CHAR_SIZE = 256; // Each character is encoded in utf-8 so 8-bit -const EXTRACT_CHAR_MASK = 2 ** 248 - CHAR_SIZE; // Mask to retreive the last character (= 0b11...1100000000) -const STRING_MAX_LEN = 2 ** 15; // The maximum index fot felt* in one direction given str[i] for i in [-2**15, 2**15) to allow back propagation for string inverse read/write operations - -@storage_var -func strings_str(str_id: felt, short_string_index: felt) -> (short_string: felt) { -} - -@storage_var -func strings_len(str_id: felt) -> (length: felt) { -} - -// -// String storage -// - -// -// Gets a string from storage based on its ID -// -// Parameters: -// str_id (felt): The ID of the string to return -// -// Returns: -// str_len (felt): The length of the string -// str (felt*): The string itself (in char array format) -// -func String_get{ - syscall_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(str_id: felt) -> (str_len: felt, str: felt*) { - alloc_locals; - let (str) = alloc(); - - let (str_len) = strings_len.read(str_id); - - if (str_len == 0) { - return (str_len, str); - } - - let (full_ss_len, rem_char_len) = unsigned_div_rem(str_len, SHORT_STRING_MAX_LEN); - - // Initiate loop with # of short strings and the last short string length - _get_ss_loop(str_id, full_ss_len, rem_char_len, str); - return (str_len, str); -} - -func _get_ss_loop{ - syscall_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(str_id: felt, ss_index: felt, ss_len: felt, str: felt*) { - let (ss_felt) = strings_str.read(str_id, ss_index); - // Get and separate each character in the short string - _get_ss_char_loop(ss_felt, ss_index, ss_len, str); - - if (ss_index == 0) { - return (); - } - // Go to the previous short string - _get_ss_loop(str_id, ss_index - 1, SHORT_STRING_MAX_LEN, str); - return (); -} - -func _get_ss_char_loop{ - syscall_ptr: felt*, bitwise_ptr: BitwiseBuiltin*, pedersen_ptr: HashBuiltin*, range_check_ptr -}(ss_felt: felt, ss_position: felt, char_index: felt, str: felt*) { - // Must be checked at beginning of function here for the case where str_len = x * SHORT_STRING_MAX_LEN - if (char_index == 0) { - return (); - } - - // Extract last character from short string - let (ss_rem, char) = String_extract_last_char(ss_felt); - - // Store the character in the correct position, i.e. SHORT_STRING_INDEX * SHORT_STRING_MAX_LEN + INDEX_IN_SHORT_STRING - assert str[ss_position * SHORT_STRING_MAX_LEN + char_index - 1] = char; - _get_ss_char_loop(ss_rem, ss_position, char_index - 1, str); - return (); -} - -// -// Sets a string in storage based on its ID -// -// Parameters: -// str_id (felt): The ID of the string to store -// str_len (felt): The length of the string -// str (felt*): The string itself (in char array format) -// -func String_set{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - str_id: felt, str_len: felt, str: felt* -) { - alloc_locals; - with_attr error_message("String : exceeding max string length 2^15") { - assert_le(str_len, STRING_MAX_LEN); - } - strings_len.write(str_id, str_len); - - if (str_len == 0) { - return (); - } - - let (full_ss_len, rem_char_len) = unsigned_div_rem(str_len, SHORT_STRING_MAX_LEN); - - // Initiate loop with # of short strings and the last short string length - _set_ss_loop(str_id, full_ss_len, rem_char_len, str); - return (); -} - -func _set_ss_loop{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - str_id: felt, ss_index: felt, ss_len: felt, str: felt* -) { - // Accumulate all characters in a felt and write it - _set_ss_char_loop(str_id, 0, ss_index, ss_len, ss_len, str); - - if (ss_index == 0) { - return (); - } - // Go to the previous short string - _set_ss_loop(str_id, ss_index - 1, SHORT_STRING_MAX_LEN, str); - return (); -} - -func _set_ss_char_loop{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - str_id: felt, ss_felt_acc: felt, ss_position: felt, ss_len: felt, char_index: felt, str: felt* -) { - if (char_index == 0) { - strings_str.write(str_id, ss_position, ss_felt_acc); - return (); - } - - let (char_offset) = pow(CHAR_SIZE, ss_len - char_index); - let ss_felt = ss_felt_acc + str[ss_position * SHORT_STRING_MAX_LEN + char_index - 1] * char_offset; - _set_ss_char_loop(str_id, ss_felt, ss_position, ss_len, char_index - 1, str); - return (); -} - -// -// Deletes a string in storage based on its ID -// -// Parameters: -// str_id (felt): The ID of the string to delete -// -func String_delete{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(str_id: felt) { - alloc_locals; - let (str_len) = strings_len.read(str_id); - - if (str_len == 0) { - return (); - } - - strings_len.write(str_id, 0); - - let (ss_cells, _) = unsigned_div_rem(str_len, SHORT_STRING_MAX_LEN); - _delete_loop(str_id, ss_cells); - return (); -} - -func _delete_loop{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - str_id: felt, ss_index: felt -) { - strings_str.write(str_id, ss_index, 0); - - if (ss_index == 0) { - return (); - } - - _delete_loop(str_id, ss_index - 1); - return (); -} - -// -// String manipulation -// - -// -// Converts a felt to its utf-8 string value -// e.g. 12345 -> 0x3132333435 -> (5, [49, 50, 51, 52, 53]) -> "12345" -// -// Parameters: -// elem (felt): The felt value to convert -// -// Returns: -// str_len (felt): The length of the string -// str (felt*): The string itself (in char array format) -// -func String_felt_to_string{range_check_ptr}(elem: felt) -> (str_len: felt, str: felt*) { - let (str_seed) = alloc(); - return _felt_to_string_loop(elem, str_seed, 0); -} - -func _felt_to_string_loop{range_check_ptr}(elem: felt, str_seed: felt*, index: felt) -> ( - str_len: felt, str: felt* -) { - alloc_locals; - with_attr error_message("String : exceeding max string length 2^15") { - assert_le(index, STRING_MAX_LEN); - } - let str_arr = cast(str_seed - 1, felt*); - - let (new_elem, unit) = unsigned_div_rem(elem, 10); - assert str_arr[0] = unit + '0'; // add '0' (= 48) to a number in range [0, 9] for utf-8 character code - if (new_elem == 0) { - return (index + 1, str_arr); - } - - let is_lower = is_le(elem, new_elem); - if (is_lower != 0) { - return (index + 1, str_arr); - } - - return _felt_to_string_loop(new_elem, str_arr, index + 1); -} - -// -// Joins to strings together and adding a '/' in between if needed -// e.g. path_join("sekai.gg", "assets") -> "sekai.gg/assets" -// -// Parameters: -// base_len (felt): The first string's length -// base (felt*): The first string -// str_len (felt): The second string's length -// str (felt*): The second string -// -// Returns: -// str_len (felt): The length of the string -// str (felt*): The string itself (in char array format) -// -func String_path_join{range_check_ptr}(base_len: felt, base: felt*, str_len: felt, str: felt*) -> ( - res_len: felt, res: felt* -) { - if (base[base_len - 1] == '/') { - return concat_arr(base_len, base, str_len, str); - } - - assert base[base_len] = '/'; // append the '/' to the first string - return concat_arr(base_len + 1, base, str_len, str); -} - -// -// Appends two strings together -// ** Wrapper of Array.concat_arr ** -// -// Parameters: -// base_len (felt): The first string's length -// base (felt*): The first string -// str_len (felt): The second string's length -// str (felt*): The second string -// -// Returns: -// str_len (felt): The length of the string -// str (felt*): The string itself (in char array format) -// -func String_append{range_check_ptr}(base_len: felt, base: felt*, str_len: felt, str: felt*) -> ( - res_len: felt, res: felt* -) { - return concat_arr(base_len, base, str_len, str); -} - -// -// Extracts the last character from a short string and returns the characters before as a short string -// Manages felt up to 2**248 - 1 (instead of unsigned_div_rem which is limited by rc_bound) -// _On the down side it requires BitwiseBuiltin for the whole call chain_ -// -// Parameters: -// ss (felt): The shortstring -// -// Returns: -// ss_rem (felt): All the characters before as a short string -// char (felt): The last character -// -func String_extract_last_char{bitwise_ptr: BitwiseBuiltin*, range_check_ptr}(ss: felt) -> ( - ss_rem: felt, char: felt -) { - with_attr error_message("String : exceeding max short string value 2^248 - 1") { - // We should assert 248 bit here but for now it's "enough" for starters - // assert_le is limited by RANGE_CHECK_BOUND - assert_250_bit(ss); - } - - let (masked_value) = bitwise_and(ss, EXTRACT_CHAR_MASK); - let ss_rem = masked_value / CHAR_SIZE; - let char = ss - masked_value; - - return (ss_rem, char); -} diff --git a/contracts/utils/ex00_base.cairo b/contracts/utils/ex00_base.cairo deleted file mode 100644 index 449ee32..0000000 --- a/contracts/utils/ex00_base.cairo +++ /dev/null @@ -1,160 +0,0 @@ -// ######## Ex 00 -// # A contract from which other contracts can import functions - -%lang starknet - -from contracts.token.ERC20.ITDERC20 import ITDERC20 -from contracts.utils.Iplayers_registry import Iplayers_registry -from starkware.cairo.common.cairo_builtins import HashBuiltin -from starkware.cairo.common.uint256 import ( - Uint256, - uint256_add, - uint256_sub, - uint256_le, - uint256_lt, - uint256_check, -) -from starkware.cairo.common.math import assert_not_zero -from starkware.starknet.common.syscalls import get_contract_address, get_caller_address -// -// Declaring storage vars -// Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity -// - -@storage_var -func tderc20_address_storage() -> (tderc20_address_storage: felt) { -} - -@storage_var -func players_registry_storage() -> (tderc20_address_storage: felt) { -} - -@storage_var -func workshop_id_storage() -> (workshop_id_storage: felt) { -} - -@storage_var -func Teacher_accounts(account: felt) -> (balance: felt) { -} - -// -// Declaring getters -// Public variables should be declared explicitely with a getter -// - -@view -func tderc20_address{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - _tderc20_address: felt -) { - let (_tderc20_address) = tderc20_address_storage.read(); - return (_tderc20_address,); -} - -@view -func players_registry{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - _players_registry: felt -) { - let (_players_registry) = players_registry_storage.read(); - return (_players_registry,); -} - -@view -func has_validated_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, exercise_id: felt -) -> (has_validated_exercise: felt) { - // reading player registry - let (_players_registry) = players_registry_storage.read(); - let (_workshop_id) = workshop_id_storage.read(); - // Checking if the user already validated this exercise - let (has_current_user_validated_exercise) = Iplayers_registry.has_validated_exercise( - contract_address=_players_registry, - account=account, - workshop=_workshop_id, - exercise=exercise_id, - ); - return (has_current_user_validated_exercise,); -} - -// -// Internal constructor -// This function is used to initialize the contract. It can be called from the constructor -// - -func ex_initializer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - _tderc20_address: felt, _players_registry: felt, _workshop_id: felt -) { - tderc20_address_storage.write(_tderc20_address); - players_registry_storage.write(_players_registry); - workshop_id_storage.write(_workshop_id); - return (); -} - -// -// Internal functions -// These functions can not be called directly by a transaction -// Similar to internal functions in Solidity -// - -func distribute_points{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - to: felt, amount: felt -) { - // Converting felt to uint256. We assume it's a small number - // We also add the required number of decimals - let points_to_credit: Uint256 = Uint256(amount * 1000000000000000000, 0); - // Retrieving contract address from storage - let (contract_address) = tderc20_address_storage.read(); - // Calling the ERC20 contract to distribute points - ITDERC20.distribute_points(contract_address=contract_address, to=to, amount=points_to_credit); - return (); -} - -func validate_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, exercise_id -) { - // reading player registry - let (_players_registry) = players_registry_storage.read(); - let (_workshop_id) = workshop_id_storage.read(); - // Checking if the user already validated this exercise - let (has_current_user_validated_exercise) = Iplayers_registry.has_validated_exercise( - contract_address=_players_registry, - account=account, - workshop=_workshop_id, - exercise=exercise_id, - ); - assert (has_current_user_validated_exercise) = 0; - - // Marking the exercise as completed - Iplayers_registry.validate_exercise( - contract_address=_players_registry, - account=account, - workshop=_workshop_id, - exercise=exercise_id, - ); - - return (); -} - -func only_teacher{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - let (caller) = get_caller_address(); - let (permission) = Teacher_accounts.read(account=caller); - assert permission = 1; - return (); -} - -@external -func set_teacher{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, permission: felt -) { - only_teacher(); - Teacher_accounts.write(account, permission); - - return (); -} - -@view -func isTeacher{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(account: felt) -> ( - permission: felt -) { - let (permission: felt) = Teacher_accounts.read(account); - return (permission,); -} diff --git a/contracts/utils/players_registry.cairo b/contracts/utils/players_registry.cairo deleted file mode 100644 index 054c37f..0000000 --- a/contracts/utils/players_registry.cairo +++ /dev/null @@ -1,213 +0,0 @@ -// ######## Players registry -// # A contract to record all addresses who participated, and which exercises and workshops they completed - -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin -from starkware.cairo.common.uint256 import ( - Uint256, - uint256_add, - uint256_sub, - uint256_le, - uint256_lt, - uint256_check, -) -from starkware.cairo.common.math import assert_not_zero -from starkware.starknet.common.syscalls import get_caller_address -// -// Declaring storage vars -// Storage vars are by default not visible through the ABI. They are similar to "private" variables in Solidity -// - -@storage_var -func has_validated_exercise_storage(account: felt, workshop: felt, exercise: felt) -> ( - has_validated_exercise_storage: felt -) { -} - -@storage_var -func exercises_and_admins_accounts(account: felt) -> (permission: felt) { -} - -@storage_var -func next_player_rank_storage() -> (next_player_rank_storage: felt) { -} - -@storage_var -func players_registry_storage(rank: felt) -> (account: felt) { -} - -@storage_var -func players_ranks_storage(account: felt) -> (rank: felt) { -} - -// -// Declaring getters -// Public variables should be declared explicitely with a getter -// - -@view -func has_validated_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, workshop: felt, exercise: felt -) -> (has_validated_exercise: felt) { - let (has_validated_exercise) = has_validated_exercise_storage.read(account, workshop, exercise); - return (has_validated_exercise,); -} - -@view -func is_exercise_or_admin{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt -) -> (permission: felt) { - let (permission: felt) = exercises_and_admins_accounts.read(account); - return (permission,); -} - -@view -func next_player_rank{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - next_player_rank: felt -) { - let (next_player_rank) = next_player_rank_storage.read(); - return (next_player_rank,); -} - -@view -func players_registry{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - rank: felt -) -> (account: felt) { - let (account) = players_registry_storage.read(rank); - return (account,); -} - -@view -func player_ranks{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt -) -> (rank: felt) { - let (rank) = players_ranks_storage.read(account); - return (rank,); -} - -// -// Events -// Keeping tracks of what happened -// -@event -func modificate_exercise_or_admin(account: felt, permission: felt) { -} - -@event -func new_player(account: felt, rank: felt) { -} - -@event -func new_validation(account: felt, workshop: felt, exercise: felt) { -} - -// -// Internal constructor -// This function is used to initialize the contract. It can be called from the constructor -// - -@constructor -func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - first_admin: felt -) { - exercises_and_admins_accounts.write(first_admin, 1); - modificate_exercise_or_admin.emit(account=first_admin, permission=1); - next_player_rank_storage.write(1); - return (); -} - -// -// Internal functions -// These functions can not be called directly by a transaction -// Similar to internal functions in Solidity -// - -func only_exercise_or_admin{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() { - let (caller) = get_caller_address(); - let (permission) = exercises_and_admins_accounts.read(account=caller); - assert permission = 1; - return (); -} - -func _set_exercises_or_admins{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - accounts_len: felt, accounts: felt* -) { - if (accounts_len == 0) { - // Start with sum=0. - return (); - } - - // If length is NOT zero, then the function calls itself again, by moving forward one slot - _set_exercises_or_admins(accounts_len=accounts_len - 1, accounts=accounts + 1); - - // This part of the function is first reached when length=0. - exercises_and_admins_accounts.write([accounts], 1); - modificate_exercise_or_admin.emit(account=[accounts], permission=1); - - return (); -} - -// -// External functions -// -// -// - -@external -func set_exercise_or_admin{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, permission: felt -) { - only_exercise_or_admin(); - exercises_and_admins_accounts.write(account, permission); - modificate_exercise_or_admin.emit(account=account, permission=permission); - - return (); -} - -@external -func set_exercises_or_admins{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - accounts_len: felt, accounts: felt* -) { - only_exercise_or_admin(); - _set_exercises_or_admins(accounts_len, accounts); - return (); -} - -@external -func validate_exercise{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - account: felt, workshop: felt, exercise: felt -) { - only_exercise_or_admin(); - // Checking if the user already validated this exercise - let (has_current_user_validated_exercise) = has_validated_exercise_storage.read( - account, workshop, exercise - ); - assert (has_current_user_validated_exercise) = 0; - - // Marking the exercise as completed - has_validated_exercise_storage.write(account, workshop, exercise, 1); - new_validation.emit(account=account, workshop=workshop, exercise=exercise); - - // Recording player if he is not yet recorded - let (player_rank) = players_ranks_storage.read(account); - - if (player_rank == 0) { - // Player is not yet record, let's record - let (next_player_rank) = next_player_rank_storage.read(); - players_registry_storage.write(next_player_rank, account); - players_ranks_storage.write(account, next_player_rank); - let next_player_rank_plus_one = next_player_rank + 1; - next_player_rank_storage.write(next_player_rank_plus_one); - new_player.emit(account=account, rank=next_player_rank); - tempvar syscall_ptr = syscall_ptr; - tempvar pedersen_ptr = pedersen_ptr; - tempvar range_check_ptr = range_check_ptr; - } else { - tempvar syscall_ptr = syscall_ptr; - tempvar pedersen_ptr = pedersen_ptr; - tempvar range_check_ptr = range_check_ptr; - } - - return (); -} diff --git a/deploy/deploying.txt b/deploy/deploying.txt deleted file mode 100644 index 7749d68..0000000 --- a/deploy/deploying.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Deploy TDERC20 -nile deploy TDERC20 327360763727160756219953 327360763727160756219953 0 0 630921626810232507712044280983612479889477627366728615579512531114753636522 630921626810232507712044280983612479889477627366728615579512531114753636522 --network goerli - -# Deploy players registry -nile deploy players_registry 630921626810232507712044280983612479889477627366728615579512531114753636522 --network goerli - -# Deploy dummy token -nile deploy dummy_token 323287074983686041199982 4478027 100000000000000000000 0 630921626810232507712044280983612479889477627366728615579512531114753636522 --network goerli - -(name: felt, symbol: felt, owner: felt, base_token_uri_len: felt, base_token_uri: felt*, token_uri_suffix: felt): -# Deploy dummy ERC721 -nile deploy TDERC721_metadata 6072054417219596849 6072054417219596849 630921626810232507712044280983612479889477627366728615579512531114753636522 3 184555836509371486644298270517380613565396767415278678887948391494588524912 181013377130045435659890581909640190867353010602592517226438742938315085926 2194400143691614193218323824727442803459257903 199354445678 --network goerli - - -# Deploy evaluator -nile deploy Evaluator 1107232797676283848029894104176837626874223129110999361753526057217367850066 1627466089830850937708126502601734844782770140122885808108717224339306362478 3 1304456572148154149118963667627194519243946039356160977623113801379917950989 3616808666604079966522808749982769827302323158913523391441632484692622841784 --network goerli - -# Set random value stores -nile invoke 0x03b56add608787daa56932f92c6afbeb50efdd78d63610d9a904aae351b6de73 set_random_values 100 2 7 4 8 7 6 1 7 6 5 4 8 8 5 6 3 8 2 8 6 5 7 3 1 8 6 7 3 6 8 1 7 3 8 2 3 4 5 2 5 7 3 3 4 4 4 5 8 1 7 1 5 7 1 3 2 5 7 8 8 7 1 8 4 1 6 2 1 6 6 4 7 2 1 2 3 5 1 3 8 6 5 5 2 7 8 4 6 4 5 4 6 1 6 4 5 3 5 8 3 0 --network goerli -nile invoke 0x03b56add608787daa56932f92c6afbeb50efdd78d63610d9a904aae351b6de73 set_random_values 100 1 1 2 1 1 1 2 2 2 2 1 2 2 2 2 1 2 1 1 1 1 2 2 2 2 2 2 2 2 1 2 1 1 2 1 2 2 1 2 1 1 1 2 2 2 2 2 1 1 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 2 1 2 1 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 2 2 1 1 2 1 2 2 1 2 2 1 1 1 2 2 2 1 --network goerli -nile invoke 0x03b56add608787daa56932f92c6afbeb50efdd78d63610d9a904aae351b6de73 set_random_values 100 4 2 4 2 2 1 2 4 3 4 4 2 3 1 1 3 4 4 1 1 4 4 2 1 1 2 1 4 3 1 2 3 3 1 4 2 4 3 4 2 4 3 3 3 4 3 1 4 2 3 3 2 1 2 3 2 3 2 2 3 3 3 1 3 3 4 3 4 4 4 3 4 4 4 1 4 4 1 3 1 1 3 2 3 2 2 4 2 3 1 3 1 1 2 2 2 2 4 4 2 2 --network goerli - - -# Finish evaluator setup -nile invoke 0x03b56add608787daa56932f92c6afbeb50efdd78d63610d9a904aae351b6de73 finish_setup --network goerli - -# Set evaluator as admin in ERC20 through voyager -# Set evaluator as admin in players registry through voyager - - diff --git a/src/deploy_doc.md b/deploy/deployment-testnet1.md similarity index 98% rename from src/deploy_doc.md rename to deploy/deployment-testnet1.md index 591f8a6..34628ea 100644 --- a/src/deploy_doc.md +++ b/deploy/deployment-testnet1.md @@ -8,7 +8,6 @@ | Player Registry | 0x53eb2d57dbc61faec5df58bd5c872c6d42bb27a6c0e434caa33091919ab61a1 | 0x012f6e9c0d1dd578c673bbbde35cd0e6e0990d0246f1c7adb3e20c6121ad08bf | TBA | | TDERC20 | 0x07c75b9f9e69b7126aa71dbc14d81eede1145fc175a7ee19e7c8c77a25e6c2b0 | 0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801 | TBA | | --------- | ---------- | ----------------- | ---------- | -| Evaluator | TBA | TBA | TBA | ## Useful comands: diff --git a/deploy/genJsonMetadata.py b/deploy/genJsonMetadata.py deleted file mode 100644 index c4afbfc..0000000 --- a/deploy/genJsonMetadata.py +++ /dev/null @@ -1,10 +0,0 @@ -import json -for i in range(1,101): - myJson = {} - myJson["name"] = "Gan generated image %s" % i - myJson["image"] = "https://gateway.pinata.cloud/ipfs/Qmd9PegtrP3c7r6uJMWTC3CMCQUTVTzqg8jtmZsxnuUAeD/" + str(i) + ".jpeg" - print(myJson) - with open("assets/%s.json" % i, 'w') as outfile: - outfile.write(json.dumps(myJson)) - # json.dumps("assets/%s.json\÷\//\" % i, myJson) - \ No newline at end of file diff --git a/deploy/genRandArgs.py b/deploy/genRandArgs.py deleted file mode 100644 index 1818d64..0000000 --- a/deploy/genRandArgs.py +++ /dev/null @@ -1,8 +0,0 @@ -import random -length = 100 -myString = "" -for i in range(0,100): - myString += " " + str(random.randint(1, 4)) -myString = str(length) + myString - -print(myString) \ No newline at end of file diff --git a/src/utils/helper.py b/deploy/helper.py similarity index 100% rename from src/utils/helper.py rename to deploy/helper.py diff --git a/src/utils/sample_name.json b/deploy/sample_name.json similarity index 100% rename from src/utils/sample_name.json rename to deploy/sample_name.json diff --git a/src/utils/sample_symbol.json b/deploy/sample_symbol.json similarity index 100% rename from src/utils/sample_symbol.json rename to deploy/sample_symbol.json diff --git a/src/README.md b/src/README.md index 02a3fe5..3a62c9e 100644 --- a/src/README.md +++ b/src/README.md @@ -1,4 +1,6 @@ -## Tasks List +# Starknet ERC721 - An Automated Workshop + +## Introduction Today, we are creating your first ERC721 from the ground up on Starknet. The ERC721 token standard stands for non-fungible tokens, also known as NFTs. @@ -6,9 +8,41 @@ The contract interface of the ERC721 that you will need to follow can be found i Now, let's get our hands dirty! -## Part 1: Creating an ERC721 +## What you will learn + +- Understanding the basisc of an ERC721 contract +- How to create, implement and deploy an ERC721 contract +- How to interact with Evaluator Contract and validate the exercises + +## Disclaimer + +​Don’t expect any benefit from using this other than learning some cool stuff about Starknet, the first general-purpose Validity Rollup on the Ethereum mainnet. + +## Steps + +Your objective is to finish the tutorial, and collect all the points.You will mostly interact with the Evaluator contract which can be found in the table below. + +| Contract Code | Contract on Starkscan | Contract on Voyager | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [Evaluator](https://github.com/starknet-edu/starknet-erc721/blob/main/src/evaluator.cairo) | [Link](https://testnet.starkscan.co/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155#read-write-contract-sub-read) | [Link](https://goerli.voyager.online/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155) | +| [Points Counter ERC20](https://github.com/starknet-edu/starknet-erc721/blob/main/src/token/TDERC20.cairo) | [Link](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | [Link](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | + +### Counting your points and checking your progress + +Your points will be credited to your wallet, though this may take some time. If you want to monitor your points count in real-time, you can also check your balance in a block explorer! + +- Go to the ERC20 counter on [Voyager](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) or [Starkscan](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) in the "read contract" tab. +- Enter your address in the `balanceOf` function.​ + +Enjoy the workshop! If you have any questions, feel free to contact us on [Discord](https://starknet.io/discord). We are happy to help! + +--- + +## Tasks list + +Before we begin, make sure to check out the `IERC721.cairo` which is interface for the ERC721. -### Exercise 1 - Deploying and initilizing your ERC721 +### Exercise 1 - Deploying and initilizing your ERC721 (2 points) First exercise of this part is to create your ERC721 Contract and your constructor function. @@ -25,7 +59,7 @@ First exercise of this part is to create your ERC721 Contract and your construct 4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. 5. Call `ex_01_erc721_init()` to verify your contract and receive points. -### Exercise 2 - Minting a token +### Exercise 2 - Minting a token (2 points) Here, we will focus on minting your first NFT. @@ -34,7 +68,7 @@ Here, we will focus on minting your first NFT. 3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. 4. Call `ex_02_erc721_mint()` to verify your contract and receive points. -### Exercise 3 - Burning a token +### Exercise 3 - Burning a token (2 points) Here, we will focus on creating the burn function. @@ -44,7 +78,7 @@ Here, we will focus on creating the burn function. 4. Send a token to the Evaluator contract by using the mint function from your deployed function. 5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. -### Exercise 4 - Approve function +### Exercise 4 - Approve function (2 points) 1. Create the `approve()` function 2. Create the `get_approved()` function for the Evaluator to receive the results back @@ -52,7 +86,7 @@ Here, we will focus on creating the burn function. 4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. 5. Call `ex_04_erc721_approve()` to verify your contract and receive points. -### Exercise 5 - Approve all function +### Exercise 5 - Approve all function (2 points) 1. Create the `set_approval_for_all()` function 2. Create the `is_approved_for_all()` function for the Evaluator to receive the results back @@ -60,7 +94,7 @@ Here, we will focus on creating the burn function. 4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. 5. Call `ex_05_erc721_approve_for_all()` to verify your contract and receive points. -### Exercise 6 - Transfering a token +### Exercise 6 - Transfering a token (2 points) Here, we will focus on creating the transfer function. @@ -68,3 +102,42 @@ Here, we will focus on creating the transfer function. 2. Deploy your contract on testnet 3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. 4. Call `ex_06_erc721_transfer()` to verify your contract and receive points. + +--- + +## Contributing to improve this workshop + +This project can be made better and will evolve. Your contributions are welcome! Go to the CONTRIBUTING file for more information on how to setup your environment and contribute to the project. + +Here are some things that you can do to help: + +Create a branch with a translation to your language +Correct bugs if you find some +Add an explanation in the comments of the exercise if you feel it needs more explanation +Add exercises showcasing your favorite Cairo feature +Add a new tutorial to the series + +## Other Automated Workshops + +This workshop is the first in a series aimed at teaching how to build on Starknet. Checkout out other workshops in the series: + +| Topic | GitHub repo | +| ------------------------------------------- | -------------------------------------------------------------------------------------- | +| Learn how to read Cairo code (you are here) | [Cairo 101](https://github.com/starknet-edu/starknet-cairo-101) | +| Deploy and customize an ERC721 NFT | [Starknet ERC721](https://github.com/starknet-edu/starknet-erc721) | +| Deploy and customize an ERC20 token | [Starknet ERC20](https://github.com/starknet-edu/starknet-erc20) | +| Build a cross-layer application | [Starknet messaging bridge](https://github.com/starknet-edu/starknet-messaging-bridge) | +| Debug your Cairo contracts easily | [Starknet debug](https://github.com/starknet-edu/starknet-debug) | +| Design your own account contract | [Starknet account abstraction](https://github.com/starknet-edu/starknet-accounts) | + +### Providing feedback & getting help + +Once you are done working on this tutorial, your feedback will be greatly appreciated! + + + +And if you struggle to move forward, do let us know! This workshop is meant to be as accessible as possible; we want to see if it’s not the case. +​ +Do you have a question? Join our [Discord server](https://starknet.io/discord), register, and join channel #tutorials-support. + +Are you interested in attending online workshops about dev on Starknet? [Subscribe here](https://starknet.substack.com/) From 322eb1fe2241efee7bfe11c5a5bbcb8644562ccb Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 13:33:41 +0200 Subject: [PATCH 06/11] moved readme to main folder --- README.es.md | 276 ------------------------------------------- README.md | 315 +++++++++++++++----------------------------------- src/README.md | 143 ----------------------- 3 files changed, 93 insertions(+), 641 deletions(-) delete mode 100644 README.es.md delete mode 100644 src/README.md diff --git a/README.es.md b/README.es.md deleted file mode 100644 index 0a53987..0000000 --- a/README.es.md +++ /dev/null @@ -1,276 +0,0 @@ -# Tutorial ERC721 en Starknet - -¡Bienvenidos! Este es un taller automatizado que explicará cómo implementar un token ERC721 en Starknet y personalizarlo para realizar funciones específicas. El estándar ERC721 se describe [aquí](https://docs.openzeppelin.com/contracts/3.x/api/token/erc721). Está dirigido a desarrolladores que: - -- Comprender la sintaxis de Cairo -- Comprender el estándar de token ERC721 . - -## Introducción - -### Atención - -No espere ningún tipo de beneficio al usar esto, aparte de aprender un montón de cosas interesantes sobre Starknet, el primer Validity Rollup de propósito general en Ethereum Mainnet. - -Starknet todavía está en Alfa. Esto significa que el desarrollo está en curso y que la pintura no está seca en todas partes. Las cosas mejorarán y, mientras tanto, ¡hacemos que las cosas funcionen con un poco de cinta adhesiva aquí y allá! - -### ¿Cómo funciona? - -El objetivo de este tutorial es personalizar e implementar un contrato ERC721 en Starknet. Su progreso será verificado por un contrato de [evaluator contract](contracts/Evaluator.cairo), implementado en Starknet, que le otorgará puntos en forma de [ERC20 tokens](contracts/token/ERC20/TDERC20.cairo). - -Cada ejercicio requerirá que agregue funcionalidad a su token ERC721. - -Para cada ejercicio, deberá escribir una nueva versión en su contrato, implementarlo y enviarlo al evaluador para su corrección. - -### ¿Dónde estoy? - -Este taller es el segundo de una serie destinada a enseñar cómo construir en Starknet. Echa un vistazo a lo siguiente: -​ -| Tema | GitHub repo | -| ---------------------------------------------- | -------------------------------------------------------------------------------------- | -| Aprenda a leer el código escrito en Cairo | [Cairo 101](https://github.com/starknet-edu/starknet-cairo-101) | -| Implemente y personalice un ERC721 NFT (aquí) | [Starknet ERC721](https://github.com/starknet-edu/starknet-erc721) | -| Implemente y personalice un token ERC20 | [Starknet ERC20](https://github.com/starknet-edu/starknet-erc20) | -| Cree una app multi capa | [Starknet messaging bridge](https://github.com/starknet-edu/starknet-messaging-bridge) | -| Depure fácilmentes sus contratos escritos en Cairo| [Starknet debug](https://github.com/starknet-edu/starknet-debug) | -| Diseña tu propio contrato de cuenta | [Starknet account abstraction](https://github.com/starknet-edu/starknet-accounts) | - - -### Proporcionar comentarios y obtener ayuda - -Una vez que haya terminado de trabajar en este tutorial, ¡sus comentarios serán muy apreciados! - -Complete [este formulario](https://forms.reform.app/starkware/untitled-form-4/kaes2e) para informarnos qué podemos hacer para mejorarlo. - -Y si tiene dificultades para seguir adelante, ¡háganoslo saber! Este taller está destinado a ser lo más accesible posible; queremos saber si no es el caso. - -¿Tienes alguna pregunta? Únase a nuestro servidor [Discord server](https://starknet.io/discord), regístrese y únase al canal #tutorials-support. ¿Está interesado en seguir talleres en línea sobre cómo aprender a desarrollar en Starknet? [Subscríbete aquí](http://eepurl.com/hFnpQ5) - -### Contribuyendo - -Este proyecto se puede mejorar y evolucionará a medida que Starknet madure. ¡Sus contribuciones son bienvenidas! Aquí hay cosas que puede hacer para ayudar: - -- Crea una sucursal con una traducción a tu idioma. -- Corrija los errores si encuentra algunos. -- Agregue una explicación en los comentarios del ejercicio si cree que necesita más explicación. -- Agregue ejercicios que muestren su característica favorita de Cairo​. - - -## Preparándose para trabajar - -### Paso 1: Clonar el repositorio - -- Oficial: - -```bash -git clone https://github.com/starknet-edu/starknet-erc721 -cd starknet-erc721 -``` - -### Paso 2: Configure su entorno - -Hay dos formas de configurar su entorno en Starknet: Una instalación local o usando un contenedor docker. - -- Para usuarios de Mac y Linux, recomendamos either -- Para usuarios de Windows recomendamos docker - -Para obtener instrucciones de configuración de producción, escribimos [este artículo](https://medium.com/starknet-edu/the-ultimate-starknet-dev-environment-716724aef4a7). - -#### Opción A: Configurar un entorno Python local - -Configure el entorno siguiendo [estas instrucciones](https://starknet.io/docs/quickstart.html#quickstart) -- Instalar [OpenZeppelin's cairo contracts](https://github.com/OpenZeppelin/cairo-contracts). - -```bash -pip install openzeppelin-cairo-contracts -``` - -#### Opción B: Usar un entorno dockerizado - -- Linux y macos - -Para mac m1: - -```bash -alias cairo='docker run --rm -v "$PWD":"$PWD" -w "$PWD" shardlabs/cairo-cli:latest-arm' -``` - -Para amd procesadores - -```bash -alias cairo='docker run --rm -v "$PWD":"$PWD" -w "$PWD" shardlabs/cairo-cli:latest' -``` - -- Windows - -```bash -docker run --rm -it -v ${pwd}:/work --workdir /work shardlabs/cairo-cli:latest -``` - -#### Paso 3: Pruebe que puede compilar el proyecto contratos de compilación - -```bash -starknet-compile contracts/Evaluator.cairo -``` - -## Trabajando en el tutorial - -### Flujo de trabajo - -Para hacer este tutorial tendrás que interactuar con el contrato [`Evaluator.cairo`](contracts/Evaluator.cairo). Para validar un ejercicio tendrás que: - -- Leer el código del evaluador para averiguar qué se espera de su contrato. -- Personaliza el código de tu contrato. -- Despliéguelo en la red de prueba de Starknet. Esto se hace usando la CLI. -- Registre su ejercicio para corrección, usando la función de `submit_exercise` en el evaluador. Esto se hace usando Voyager. -- Llame a la función correspondiente en el contrato del evaluador para corregir su ejercicio y recibir sus puntos. Esto se hace usando Voyager. - -Por ejemplo para resolver el primer ejercicio el flujo de trabajo sería el siguiente: - - -`deploy a smart contract that answers ex1` → `call submit_exercise on the evaluator providing your smart contract address` → `call ex1_test_erc721 on the evaluator contract` - -**Su objetivo es reunir tantos puntos ERC721-101 como sea posible.** Tenga en cuenta : - -- La función de 'transferencia' de ERC721-101 ha sido deshabilitada para alentarlo a terminar el tutorial con una sola dirección. Para recibir puntos, el evaluador debe alcanzar las llamadas a la función distribuir_punto. -- Este repositorio contiene una interfaz `IExerciseSolution.cairo`. Su contrato ERC721 deberá ajustarse a esta interfaz para validar algunos ejercicios; es decir, su contrato debe implementar todas las funciones descritas en `IExerciseSolution.cairo`. - -- **Realmente recomendamos que lea el contrato de [`Evaluator.cairo`](contracts/Evaluator.cairo) para comprender completamente lo que se espera de cada ejercicio**. En este archivo Léame se proporciona una descripción de alto nivel de lo que se espera de cada ejercicio. - -- El contrato de Evaluador a veces necesita realizar pagos para comprar sus tokens. ¡Asegúrate de que tenga suficientes toknes faucet para hacerlo! De lo contrario, debe obtener tokens faucet del contrato de tokens faucet y enviarlos al evaluador. - -### Direcciones y contratos oficiales - -| Contract code | Contract on voyager | -| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Points counter ERC20](contracts/token/ERC20/TDERC20.cairo) | [0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707](https://goerli.voyager.online/contract/0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707) | -| [Evaluator](contracts/Evaluator.cairo) | [0x2d15a378e131b0a9dc323d0eae882bfe8ecc59de0eb206266ca236f823e0a15](https://goerli.voyager.online/contract/0x2d15a378e131b0a9dc323d0eae882bfe8ecc59de0eb206266ca236f823e0a15) | -| [Dummy ERC20 token](contracts/token/ERC20/dummy_token.cairo) | [0x52ec5de9a76623f18e38c400f763013ff0b3ff8491431d7dc0391b3478bf1f3](https://goerli.voyager.online/contract/0x52ec5de9a76623f18e38c400f763013ff0b3ff8491431d7dc0391b3478bf1f3) | -| [Dummy ERC721 token](contracts/token/ERC721/TDERC721_metadata.cairo) | [0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21](https://goerli.voyager.online/contract/0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21) | - -​​ - -## Lista de tareas - -¡Hoy estamos creando un registro de animales! Los animales son criados por criadores. Pueden nacer, morir, reproducirse, venderse. Irás implementando estas características poco a poco. - -### Ejercicio 1: Implementación de un ERC721 - -- Cree un contrato de token ERC721. Puedes usar [esta implementación](https://github.com/OpenZeppelin/cairo-contracts/blob/v0.2.1/src/openzeppelin/token/erc721/ERC721_Mintable_Burnable.cairo) como base. -- Despliéguelo en la red de prueba (verifique en el constructor los argumentos necesarios. También tenga en cuenta que los argumentos deben ser decimales). - -```bash -starknet-compile contracts/ERC721/ERC721.cairo --output artifacts/ERC721.json -starknet deploy --contract artifacts/ERC721.json --inputs arg1 arg2 arg3 --network alpha-goerli -``` - -- Entrega el token n.° 1 al contrato del evaluador. -- Llame a [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. (4 pts) -- Llame a [`ex1_test_erc721()`](contracts/Evaluator.cairo#L146) en el Evaluador para recibir sus puntos. (2 pts) - --------------- - -### Ejercicio 2: Creación de atributos de token - -- Llame a [`ex2a_get_animal_rank()`](contracts/Evaluator.cairo#L245) para que le asignen una criatura aleatoria para crear. -- Lea las características esperadas de su animal del Evaluador. -- Cree las herramientas necesarias para registrar las características de los animales en su contrato y permita que el contrato del Evaluador las recupere a través de la función `get_animal_characteristics` en su contrato [marque esto](contracts/IExerciseSolution.cairo) -- Implementa tu nuevo contrato. -- Cree el animal con las características deseadas y entregarlo al Evaluador. -- Llame [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. -- Llame a [`ex2b_test_declare_animal()`](contracts/Evaluator.cairo#L258) para recibir puntos. (2 pts) - -------------- - -### Ejercicio 3: Creación de NFT - -- Crear una función para permitir a los criadores crear nuevos animales con las características especificadas. -- Implementa tu nuevo contrato. -- Llame a [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. -- Llame a [`ex3_declare_new_animal()`](contracts/Evaluator.cairo#L272) para obtener puntos. (2 puntos) - -------------- - -### Ejercicio 4 - Quema de NFT - -- Cree una función para permitir que los criadores declaren animales muertos (quemar el NFT). -- Implementa tu nuevo contrato. -- Llame a [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. -- Llame a [`ex4_declare_dead_animal()`](contracts/Evaluator.cairo#L323) para obtener puntos. (2 puntos) - ------------ - -### Ejercicio 5 - Adición de permisos y pagos - -- Use el [dummy token faucet](contracts/token/ERC20/dummy_token.cairo) para obtener dummy token. -- Usa [`ex5a_i_have_dtk()`](contracts/Evaluator.cairo#L406) para mostrar que lograste usar el faucet. (2 pts) -- Cree una función para permitir el registro de criadores. -- Esta función debería cobrarle al registrante una tarifa, pagada en tokens faucet. ([consulte `registration_price`](contracts/IExerciseSolution.cairo)) -- Agregar permisos. Solo permitir que los criadores listados puedan crear animales. -- Implementa tu nuevo contrato. -- Llame a [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. -- Llame a [`ex5b_register_breeder()`](contracts/Evaluator.cairo#L440) para probar que su función funciona. Si es necesario, envíe tokens faucet primero al Evaluador. (2 puntos) - ---------------------- - -### Ejercicio 6 - Reclamación de un NFT - -- Cree un NFT con metadatos en [este dummy ERC721 token](contracts/token/ERC721/TDERC721_metadata.cairo), utilizable [aquí](https://goerli.voyager.online/contract/0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21). -- Compruébalo en [Aspect](https://testnet.aspect.co/). -- Reclamar puntos en [`ex6_claim_metadata_token`](contracts/Evaluator.cairo#L523). (2 puntos) - ------------------- - -### Ejercicio 7 - Adición de metadatos - -- Cree un nuevo contrato ERC721 que admita metadatos. Puedes usar como base [este contrato](contracts/token/ERC721/ERC721_metadata.cairo) -- El URI del token base es la puerta de enlace IPFS elegida. -- Puede cargar sus NFT directamente en [este website](https://www.pinata.cloud/) -- ¡Tus tokens deberían ser visibles en [Aspect](https://testnet.aspect.co/) una vez creados! -- Implementa tu nuevo contrato. -- Llame a [`submit_exercise()`](contracts/Evaluator.cairo#L601) en el Evaluador para configurar el contrato que desea evaluar. -- Reclamar puntos en [`ex7_add_metadata`](contracts/Evaluator.cairo#L557) (2 puntos) - ------------------- - -## ​Anexo - Herramientas útiles - -### Conversión de datos a y desde decimal - -Para convertir datos en felt, use el script [`utils.py`](utils.py). -Para abrir Python en modo interactivo después de ejecutar el script. - -```bash - python -i utils.py - ``` - - ```python - >>> str_to_felt('ERC20-101') - 1278752977803006783537 - ``` - -Si da error pruebe: - -```bash - python3 -i utils.py - ``` - - ```python - >>> str_to_felt('ERC20-101') - 1278752977803006783537 - ``` - -### Comprobando tu progreso y contando tus puntos - -Sus puntos se acreditarán en su billetera; aunque esto puede tomar algún tiempo. Si desea monitorear su conteo de puntos en tiempo real, ¡también puede ver su saldo en voyager! - -- ​Vaya al contador [ERC20 counter](https://goerli.voyager.online/contract/0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707#readContract) en voyager, en la pestaña "leer contrato" -- Ingrese su dirección en decimal en la función "balanceOf" - -También puede consultar su progreso general [aquí](https://starknet-tutorials.vercel.app). - -### Estado de la transacción - -¿Envió una transacción y se muestra como "no detectada" en voyager? Esto puede significar dos cosas: - -- Su transacción está pendiente y se incluirá en un bloque en breve. Entonces será visible en Voyager. -- Su transacción no fue válida y NO se incluirá en un bloque (no existe una transacción fallida en Starknet). Puede (y debe) verificar el estado de su transacción con la siguiente URL [https://alpha4.starknet.io/feeder_gateway/get_transaction_receipt?transactionHash=](https://alpha4.starknet.io/feeder_gateway/get_transaction_receipt?transactionHash=), donde puede agregar el hash de su transacción.​ diff --git a/README.md b/README.md index 6a3c9e2..3a62c9e 100644 --- a/README.md +++ b/README.md @@ -1,272 +1,143 @@ -# ERC721 on StarkNet - -Welcome! This is an automated workshop that will explain how to deploy an ERC721 token on StarkNet and customize it to perform specific functions. The ERC721 standard is described [here](https://docs.openzeppelin.com/contracts/3.x/api/token/erc721). -It is aimed at developers that: - -- Understand Cairo syntax -- Understand the ERC721 token standard -​ -​ +# Starknet ERC721 - An Automated Workshop ## Introduction -### Disclaimer - -​ -Don't expect any kind of benefit from using this, other than learning a bunch of cool stuff about StarkNet, the first general purpose validity rollup on the Ethereum Mainnet. -​ -StarkNet is still in Alpha. This means that development is ongoing, and the paint is not dry everywhere. Things will get better, and in the meanwhile, we make things work with a bit of duct tape here and there! -​ - -### How it works - -The goal of this tutorial is for you to customize and deploy an ERC721 contract on StarkNet. Your progress will be check by an [evaluator contract](contracts/Evaluator.cairo), deployed on StarkNet, which will grant you points in the form of [ERC20 tokens](contracts/token/ERC20/TDERC20.cairo). - -Each exercise will require you to add functionality to your ERC721 token. - -For each exercise, you will have to write a new version on your contract, deploy it, and submit it to the evaluator for correction. - -### Where am I? - -This workshop is the second in a series aimed at teaching how to build on StarkNet. Checkout out the following: - -| Topic | GitHub repo | -| ------------------------------------------------- | -------------------------------------------------------------------------------------- | -| Learn how to read Cairo code | [Cairo 101](https://github.com/starknet-edu/starknet-cairo-101) | -| Deploy and customize an ERC721 NFT (you are here) | [StarkNet ERC721](https://github.com/starknet-edu/starknet-erc721) | -| Deploy and customize an ERC20 token | [StarkNet ERC20](https://github.com/starknet-edu/starknet-erc20) | -| Build a cross layer application | [StarkNet messaging bridge](https://github.com/starknet-edu/starknet-messaging-bridge) | -| Debug your Cairo contracts easily | [StarkNet debug](https://github.com/starknet-edu/starknet-debug) | -| Design your own account contract | [StarkNet account abstraction](https://github.com/starknet-edu/starknet-accounts) | - -### Providing feedback & getting help - -Once you are done working on this tutorial, your feedback would be greatly appreciated! - -**Please fill out [this form](https://forms.reform.app/starkware/untitled-form-4/kaes2e) to let us know what we can do to make it better.** - -​ -And if you struggle to move forward, do let us know! This workshop is meant to be as accessible as possible; we want to know if it's not the case. - -​ -Do you have a question? Join our [Discord server](https://starknet.io/discord), register, and join channel #tutorials-support -​ -Are you interested in following online workshops about learning how to dev on StarkNet? [Subscribe here](http://eepurl.com/hFnpQ5) - -### Contributing - -This project can be made better and will evolve as StarkNet matures. Your contributions are welcome! Here are things that you can do to help: - -- Create a branch with a translation to your language -- Correct bugs if you find some -- Add an explanation in the comments of the exercise if you feel it needs more explanation -- Add exercises showcasing your favorite Cairo feature - -​ - -## Getting ready to work - -### Step 1 - Clone the repo +Today, we are creating your first ERC721 from the ground up on Starknet. The ERC721 token standard stands for non-fungible tokens, also known as NFTs. -```bash -git clone https://github.com/starknet-edu/starknet-erc721 -cd starknet-erc721 -``` +The contract interface of the ERC721 that you will need to follow can be found in `src/IERC721.cairo`. Please ensure that all the function names adhere to the IERC721 standard. -### Step 2 - Set up your environment +Now, let's get our hands dirty! -There are two ways to set up your environment on StarkNet: a local installation, or using a docker container +## What you will learn -- For Mac and Linux users, we recommend either -- For windows users we recommend docker +- Understanding the basisc of an ERC721 contract +- How to create, implement and deploy an ERC721 contract +- How to interact with Evaluator Contract and validate the exercises -For a production setup instructions we wrote [this article](https://medium.com/starknet-edu/the-ultimate-starknet-dev-environment-716724aef4a7). +## Disclaimer -#### Option A - Set up a local python environment +​Don’t expect any benefit from using this other than learning some cool stuff about Starknet, the first general-purpose Validity Rollup on the Ethereum mainnet. -- Set up the environment following [these instructions](https://docs.starknet.io/documentation/getting_started/setting_up_the_environment/) -- Install [OpenZeppelin's cairo contracts](https://github.com/OpenZeppelin/cairo-contracts). +## Steps -```bash -pip install openzeppelin-cairo-contracts -``` +Your objective is to finish the tutorial, and collect all the points.You will mostly interact with the Evaluator contract which can be found in the table below. -#### Option B - Use a dockerized environment +| Contract Code | Contract on Starkscan | Contract on Voyager | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [Evaluator](https://github.com/starknet-edu/starknet-erc721/blob/main/src/evaluator.cairo) | [Link](https://testnet.starkscan.co/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155#read-write-contract-sub-read) | [Link](https://goerli.voyager.online/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155) | +| [Points Counter ERC20](https://github.com/starknet-edu/starknet-erc721/blob/main/src/token/TDERC20.cairo) | [Link](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | [Link](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | -- Linux and macos +### Counting your points and checking your progress -for mac m1: +Your points will be credited to your wallet, though this may take some time. If you want to monitor your points count in real-time, you can also check your balance in a block explorer! -```bash -alias cairo='docker run --rm -v "$PWD":"$PWD" -w "$PWD" shardlabs/cairo-cli:latest-arm' -``` +- Go to the ERC20 counter on [Voyager](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) or [Starkscan](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) in the "read contract" tab. +- Enter your address in the `balanceOf` function.​ -for amd processors +Enjoy the workshop! If you have any questions, feel free to contact us on [Discord](https://starknet.io/discord). We are happy to help! -```bash -alias cairo='docker run --rm -v "$PWD":"$PWD" -w "$PWD" shardlabs/cairo-cli:latest' -``` - -- Windows - -```bash -docker run --rm -it -v ${pwd}:/work --workdir /work shardlabs/cairo-cli:latest -``` - -### Step 3 -Test that you are able to compile the project - -```bash -starknet-compile contracts/Evaluator.cairo -``` - -​ -​ - -## Working on the tutorial - -### Workflow - -To do this tutorial you will have to interact with the [`Evaluator.cairo`](contracts/Evaluator.cairo) contract. To validate an exercise you will have to - -- Read the evaluator code to figure out what is expected of your contract -- Customize your contract's code -- Deploy it to StarkNet's testnet. This is done using the CLI. -- Register your exercise for correction, using the `submit_exercise` function on the evaluator. This is done using Voyager. -- Call the relevant function on the evaluator contract to get your exercise corrected and receive your points. This is done using Voyager. - -For example to solve the first exercise the workflow would be the following: - -`deploy a smart contract that answers ex1` → `call submit_exercise on the evaluator providing your smart contract address` → `call ex1_test_erc721 on the evaluator contract` - -**Your objective is to gather as many ERC721-101 points as possible.** Please note : - -- The 'transfer' function of ERC721-101 has been disabled to encourage you to finish the tutorial with only one address -- In order to receive points, the evaluator has to reach the calls to the `distribute_point` function. -- This repo contains an interface `IExerciseSolution.cairo`. Your ERC721 contract will have to conform to this interface in order to validate some exercises; that is, your contract needs to implement all the functions described in `IExerciseSolution.cairo`. -- **We really recommend that your read the [`Evaluator.cairo`](contracts/Evaluator.cairo) contract in order to fully understand what's expected for each exercise**. A high level description of what is expected for each exercise is provided in this readme. -- The Evaluator contract sometimes needs to make payments to buy your tokens. Make sure he has enough dummy tokens to do so! If not, you should get dummy tokens from the dummy tokens contract and send them to the evaluator - -### Contracts code and addresses - -| Contract code | Contract on voyager | -| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Points counter ERC20](contracts/token/ERC20/TDERC20.cairo) | [0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707](https://goerli.voyager.online/contract/0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707) | -| [Evaluator](contracts/Evaluator.cairo) | [0x2d15a378e131b0a9dc323d0eae882bfe8ecc59de0eb206266ca236f823e0a15](https://goerli.voyager.online/contract/0x2d15a378e131b0a9dc323d0eae882bfe8ecc59de0eb206266ca236f823e0a15) | -| [Dummy ERC20 token](contracts/token/ERC20/dummy_token.cairo) | [0x52ec5de9a76623f18e38c400f763013ff0b3ff8491431d7dc0391b3478bf1f3](https://goerli.voyager.online/contract/0x52ec5de9a76623f18e38c400f763013ff0b3ff8491431d7dc0391b3478bf1f3) | -| [Dummy ERC721 token](contracts/token/ERC721/TDERC721_metadata.cairo) | [0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21](https://goerli.voyager.online/contract/0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21) | - -​ -​ +--- ## Tasks list -Today we are creating an animal registry! Animals are bred by breeders. They can be born, die, reproduce, be sold. You will implement these features little by little. +Before we begin, make sure to check out the `IERC721.cairo` which is interface for the ERC721. -### Exercise 1 - Deploying an ERC721 +### Exercise 1 - Deploying and initilizing your ERC721 (2 points) -- Create an ERC721 token contract. You can use [this implementation](https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.5.0/src/openzeppelin/token/erc721/presets/ERC721MintableBurnable.cairo) as a base -- Deploy it to the testnet (check the constructor for the needed arguments. Also note that the arguments should be decimals.) +First exercise of this part is to create your ERC721 Contract and your constructor function. -```bash -starknet-compile contracts/ERC721/ERC721.cairo --output artifacts/ERC721.json -starknet deploy --contract artifacts/ERC721.json --inputs arg1 arg2 arg3 --network alpha-goerli -``` +1. Create your initial ERC721 contract. You will need the following: + 1. a constructor function that takes the `name` and `symbol` as input and then initializes the contract with those inputs + 2. a `get_name()` to receive the name of the ERC721 + 3. a `get_symbol()` to receive the symbol of the ERC721 +2. Assign a user slot from the Evaluator contract by calling `assign_user_slot()` + 1. Check the `get_user_slot()` to receive your number + 2. Based on your `user_slot` number, check the `get_info_name()` and `get_info_symbol()` to receive your unique `name` and `symbol`. + 3. use these values to initialize your ERC721 +3. Deploy your contract on testnet + 1. make sure you use your given values based on the assigned user slot. +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_01_erc721_init()` to verify your contract and receive points. -- Give token #1 to Evaluator contract -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated (4 pts) -- Call [`ex1_test_erc721()`](contracts/Evaluator.cairo#L146) in the evaluator to receive your points (2 pts) +### Exercise 2 - Minting a token (2 points) -### Exercise 2 - Creating token attributes +Here, we will focus on minting your first NFT. -- Call [`ex2a_get_animal_rank()`](contracts/Evaluator.cairo#L245) to get assigned a random creature to create. -- Read the expected characteristics of your animal from the Evaluator -- Create the tools necessary to record animals characteristics in your contract and enable the evaluator contract to retrieve them trough `get_animal_characteristics` function on your contract ([check this](contracts/IExerciseSolution.cairo)) -- Deploy your new contract -- Mint the animal with the desired characteristics and give it to the evaluator -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated -- Call [`ex2b_test_declare_animal()`](contracts/Evaluator.cairo#L258) to receive points (2 pts) +1. Create the `mint()` function that allows you to mint an NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Call `ex_02_erc721_mint()` to verify your contract and receive points. -### Exercise 3 - Minting NFTs +### Exercise 3 - Burning a token (2 points) -- Create a function to allow breeders to mint new animals with the specified characteristics -- Deploy your new contract -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated -- Call [`ex3_declare_new_animal()`](contracts/Evaluator.cairo#L272) to get points (2 pts) +Here, we will focus on creating the burn function. -### Exercise 4 - Burning NFTs +1. Create the `burn()` function that allows you to burn an NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Send a token to the Evaluator contract by using the mint function from your deployed function. +5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. -- Create a function to allow breeders to declare dead animals (burn the NFT) -- Deploy your new contract -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated -- Call [`ex4_declare_dead_animal()`](contracts/Evaluator.cairo#L323) to get points (2 pts) +### Exercise 4 - Approve function (2 points) -### Exercise 5 - Adding permissions and payments +1. Create the `approve()` function +2. Create the `get_approved()` function for the Evaluator to receive the results back +3. Deploy your contract on testnet +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_04_erc721_approve()` to verify your contract and receive points. -- Use [dummy token faucet](contracts/token/ERC20/dummy_token.cairo) to get dummy tokens -- Use [`ex5a_i_have_dtk()`](contracts/Evaluator.cairo#L406) to show you managed to use the faucet (2 pts) -- Create a function to allow breeder registration. -- This function should charge the registrant for a fee, paid in dummy tokens ([check `registration_price`](contracts/IExerciseSolution.cairo)) -- Add permissions. Only allow listed breeders should be able to create animals -- Deploy your new contract -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated -- Call [`ex5b_register_breeder()`](contracts/Evaluator.cairo#L440) to prove your function works. If needed, send dummy tokens first to the evaluator (2pts) +### Exercise 5 - Approve all function (2 points) -### Exercise 6 - Claiming an NFT +1. Create the `set_approval_for_all()` function +2. Create the `is_approved_for_all()` function for the Evaluator to receive the results back +3. Deploy your contract on testnet +4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +5. Call `ex_05_erc721_approve_for_all()` to verify your contract and receive points. -- Mint a NFT with metadata on [this dummy ERC721 token](contracts/token/ERC721/TDERC721_metadata.cairo) , usable [here](https://goerli.voyager.online/contract/0x4fc25c4aca3a8126f9b386f8908ffb7518bc6fefaa5c542cd538655827f8a21) -- Check it on [Aspect](https://testnet.aspect.co/) -- Claim points on [`ex6_claim_metadata_token`](contracts/Evaluator.cairo#L523) (2 pts) +### Exercise 6 - Transfering a token (2 points) -### Exercise 7 - Adding metadata +Here, we will focus on creating the transfer function. -- Create a new ERC721 contract that supports metadata. You can use [this contract](contracts/token/ERC721/ERC721_metadata.cairo) as a base -- The base token URI is the chosen IPFS gateway -- You can upload your NFTs directly on [this website](https://www.pinata.cloud/) -- Your tokens should be visible on [Aspect](https://testnet.aspect.co/) once minted! -- Deploy your new contract -- Call [`submit_exercise()`](contracts/Evaluator.cairo#L601) in the Evaluator to configure the contract you want evaluated -- Claim points on [`ex7_add_metadata`](contracts/Evaluator.cairo#L557) (2 pts) +1. Create the `transfer_from()` function that allows you to transfer the NFT. +2. Deploy your contract on testnet +3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +4. Call `ex_06_erc721_transfer()` to verify your contract and receive points. -​ +--- -## Annex - Useful tools +## Contributing to improve this workshop -### Converting data to and from decimal +This project can be made better and will evolve. Your contributions are welcome! Go to the CONTRIBUTING file for more information on how to setup your environment and contribute to the project. -To convert data to felt use the [`utils.py`](utils.py) script -To open Python in interactive mode after running script +Here are some things that you can do to help: - ```bash - python -i utils.py - ``` +Create a branch with a translation to your language +Correct bugs if you find some +Add an explanation in the comments of the exercise if you feel it needs more explanation +Add exercises showcasing your favorite Cairo feature +Add a new tutorial to the series - ```python - >>> str_to_felt('ERC20-101') - 1278752977803006783537 - ``` +## Other Automated Workshops -### Checking your progress & counting your points +This workshop is the first in a series aimed at teaching how to build on Starknet. Checkout out other workshops in the series: -​ -Your points will get credited in your wallet; though this may take some time. If you want to monitor your points count in real time, you can also see your balance in voyager! -​ +| Topic | GitHub repo | +| ------------------------------------------- | -------------------------------------------------------------------------------------- | +| Learn how to read Cairo code (you are here) | [Cairo 101](https://github.com/starknet-edu/starknet-cairo-101) | +| Deploy and customize an ERC721 NFT | [Starknet ERC721](https://github.com/starknet-edu/starknet-erc721) | +| Deploy and customize an ERC20 token | [Starknet ERC20](https://github.com/starknet-edu/starknet-erc20) | +| Build a cross-layer application | [Starknet messaging bridge](https://github.com/starknet-edu/starknet-messaging-bridge) | +| Debug your Cairo contracts easily | [Starknet debug](https://github.com/starknet-edu/starknet-debug) | +| Design your own account contract | [Starknet account abstraction](https://github.com/starknet-edu/starknet-accounts) | -- Go to the [ERC20 counter](https://goerli.voyager.online/contract/0xa0b943234522049dcdbd36cf9d5e12a46be405d6b8757df2329e6536b40707#readContract) in voyager, in the "read contract" tab -- Enter your address in decimal in the "balanceOf" function +### Providing feedback & getting help -You can also check your overall progress [here](https://starknet-tutorials.vercel.app) -​ +Once you are done working on this tutorial, your feedback will be greatly appreciated! -### Transaction status + +And if you struggle to move forward, do let us know! This workshop is meant to be as accessible as possible; we want to see if it’s not the case. ​ -You sent a transaction, and it is shown as "undetected" in voyager? This can mean two things: -​ +Do you have a question? Join our [Discord server](https://starknet.io/discord), register, and join channel #tutorials-support. -- Your transaction is pending, and will be included in a block shortly. It will then be visible in voyager. -- Your transaction was invalid, and will NOT be included in a block (there is no such thing as a failed transaction in StarkNet). -​ -You can (and should) check the status of your transaction with the following URL [https://alpha4.starknet.io/feeder_gateway/get_transaction_receipt?transactionHash=](https://alpha4.starknet.io/feeder_gateway/get_transaction_receipt?transactionHash=) , where you can append your transaction hash. -​ - -​ +Are you interested in attending online workshops about dev on Starknet? [Subscribe here](https://starknet.substack.com/) diff --git a/src/README.md b/src/README.md deleted file mode 100644 index 3a62c9e..0000000 --- a/src/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# Starknet ERC721 - An Automated Workshop - -## Introduction - -Today, we are creating your first ERC721 from the ground up on Starknet. The ERC721 token standard stands for non-fungible tokens, also known as NFTs. - -The contract interface of the ERC721 that you will need to follow can be found in `src/IERC721.cairo`. Please ensure that all the function names adhere to the IERC721 standard. - -Now, let's get our hands dirty! - -## What you will learn - -- Understanding the basisc of an ERC721 contract -- How to create, implement and deploy an ERC721 contract -- How to interact with Evaluator Contract and validate the exercises - -## Disclaimer - -​Don’t expect any benefit from using this other than learning some cool stuff about Starknet, the first general-purpose Validity Rollup on the Ethereum mainnet. - -## Steps - -Your objective is to finish the tutorial, and collect all the points.You will mostly interact with the Evaluator contract which can be found in the table below. - -| Contract Code | Contract on Starkscan | Contract on Voyager | -| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| [Evaluator](https://github.com/starknet-edu/starknet-erc721/blob/main/src/evaluator.cairo) | [Link](https://testnet.starkscan.co/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155#read-write-contract-sub-read) | [Link](https://goerli.voyager.online/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155) | -| [Points Counter ERC20](https://github.com/starknet-edu/starknet-erc721/blob/main/src/token/TDERC20.cairo) | [Link](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | [Link](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | - -### Counting your points and checking your progress - -Your points will be credited to your wallet, though this may take some time. If you want to monitor your points count in real-time, you can also check your balance in a block explorer! - -- Go to the ERC20 counter on [Voyager](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) or [Starkscan](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) in the "read contract" tab. -- Enter your address in the `balanceOf` function.​ - -Enjoy the workshop! If you have any questions, feel free to contact us on [Discord](https://starknet.io/discord). We are happy to help! - ---- - -## Tasks list - -Before we begin, make sure to check out the `IERC721.cairo` which is interface for the ERC721. - -### Exercise 1 - Deploying and initilizing your ERC721 (2 points) - -First exercise of this part is to create your ERC721 Contract and your constructor function. - -1. Create your initial ERC721 contract. You will need the following: - 1. a constructor function that takes the `name` and `symbol` as input and then initializes the contract with those inputs - 2. a `get_name()` to receive the name of the ERC721 - 3. a `get_symbol()` to receive the symbol of the ERC721 -2. Assign a user slot from the Evaluator contract by calling `assign_user_slot()` - 1. Check the `get_user_slot()` to receive your number - 2. Based on your `user_slot` number, check the `get_info_name()` and `get_info_symbol()` to receive your unique `name` and `symbol`. - 3. use these values to initialize your ERC721 -3. Deploy your contract on testnet - 1. make sure you use your given values based on the assigned user slot. -4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -5. Call `ex_01_erc721_init()` to verify your contract and receive points. - -### Exercise 2 - Minting a token (2 points) - -Here, we will focus on minting your first NFT. - -1. Create the `mint()` function that allows you to mint an NFT. -2. Deploy your contract on testnet -3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -4. Call `ex_02_erc721_mint()` to verify your contract and receive points. - -### Exercise 3 - Burning a token (2 points) - -Here, we will focus on creating the burn function. - -1. Create the `burn()` function that allows you to burn an NFT. -2. Deploy your contract on testnet -3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -4. Send a token to the Evaluator contract by using the mint function from your deployed function. -5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. - -### Exercise 4 - Approve function (2 points) - -1. Create the `approve()` function -2. Create the `get_approved()` function for the Evaluator to receive the results back -3. Deploy your contract on testnet -4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -5. Call `ex_04_erc721_approve()` to verify your contract and receive points. - -### Exercise 5 - Approve all function (2 points) - -1. Create the `set_approval_for_all()` function -2. Create the `is_approved_for_all()` function for the Evaluator to receive the results back -3. Deploy your contract on testnet -4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -5. Call `ex_05_erc721_approve_for_all()` to verify your contract and receive points. - -### Exercise 6 - Transfering a token (2 points) - -Here, we will focus on creating the transfer function. - -1. Create the `transfer_from()` function that allows you to transfer the NFT. -2. Deploy your contract on testnet -3. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. -4. Call `ex_06_erc721_transfer()` to verify your contract and receive points. - ---- - -## Contributing to improve this workshop - -This project can be made better and will evolve. Your contributions are welcome! Go to the CONTRIBUTING file for more information on how to setup your environment and contribute to the project. - -Here are some things that you can do to help: - -Create a branch with a translation to your language -Correct bugs if you find some -Add an explanation in the comments of the exercise if you feel it needs more explanation -Add exercises showcasing your favorite Cairo feature -Add a new tutorial to the series - -## Other Automated Workshops - -This workshop is the first in a series aimed at teaching how to build on Starknet. Checkout out other workshops in the series: - -| Topic | GitHub repo | -| ------------------------------------------- | -------------------------------------------------------------------------------------- | -| Learn how to read Cairo code (you are here) | [Cairo 101](https://github.com/starknet-edu/starknet-cairo-101) | -| Deploy and customize an ERC721 NFT | [Starknet ERC721](https://github.com/starknet-edu/starknet-erc721) | -| Deploy and customize an ERC20 token | [Starknet ERC20](https://github.com/starknet-edu/starknet-erc20) | -| Build a cross-layer application | [Starknet messaging bridge](https://github.com/starknet-edu/starknet-messaging-bridge) | -| Debug your Cairo contracts easily | [Starknet debug](https://github.com/starknet-edu/starknet-debug) | -| Design your own account contract | [Starknet account abstraction](https://github.com/starknet-edu/starknet-accounts) | - -### Providing feedback & getting help - -Once you are done working on this tutorial, your feedback will be greatly appreciated! - - - -And if you struggle to move forward, do let us know! This workshop is meant to be as accessible as possible; we want to see if it’s not the case. -​ -Do you have a question? Join our [Discord server](https://starknet.io/discord), register, and join channel #tutorials-support. - -Are you interested in attending online workshops about dev on Starknet? [Subscribe here](https://starknet.substack.com/) From 5aa38facc52d6bf631b450021d62bd4ef94a4039 Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 13:51:12 +0200 Subject: [PATCH 07/11] clean up --- .gitignore | 2 ++ .vscode/settings.json | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 117957b..d429f4a 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,5 @@ dmypy.json goerli.deployments.txt Makefile + +.vscode \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 6b665aa..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "liveServer.settings.port": 5501 -} From a3d78409230e32ea76f10ed5b05b831534bc9e2d Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 14:50:30 +0200 Subject: [PATCH 08/11] update readme --- README.md | 8 ++++---- src/ERC721/IERC721.cairo | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3a62c9e..4e6241a 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,10 @@ Now, let's get our hands dirty! Your objective is to finish the tutorial, and collect all the points.You will mostly interact with the Evaluator contract which can be found in the table below. -| Contract Code | Contract on Starkscan | Contract on Voyager | -| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| [Evaluator](https://github.com/starknet-edu/starknet-erc721/blob/main/src/evaluator.cairo) | [Link](https://testnet.starkscan.co/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155#read-write-contract-sub-read) | [Link](https://goerli.voyager.online/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155) | -| [Points Counter ERC20](https://github.com/starknet-edu/starknet-erc721/blob/main/src/token/TDERC20.cairo) | [Link](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | [Link](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | +| Contract Code | Contract on Starkscan | Contract on Voyager | +| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| Evaluator | [Link](https://testnet.starkscan.co/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155#read-write-contract-sub-read) | [Link](https://goerli.voyager.online/contract/0x02e3ceda622a192488062ed6a453f8a8ebbf472a7b60aaf160cbbc6b485e4155) | +| Points Counter ERC20 | [Link](https://testnet.starkscan.co/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | [Link](https://goerli.voyager.online/contract/0x074b1195731222a7bcbb724d32b93d0c525e173b2c3e9722a2214b101c862801) | ### Counting your points and checking your progress diff --git a/src/ERC721/IERC721.cairo b/src/ERC721/IERC721.cairo index 208494c..3fd28de 100644 --- a/src/ERC721/IERC721.cairo +++ b/src/ERC721/IERC721.cairo @@ -10,12 +10,14 @@ trait IERC721 { fn get_symbol() -> felt252; fn owner_of(token_id: u256) -> ContractAddress; fn balance_of(account: ContractAddress) -> u256; + + fn approve(to: ContractAddress, token_id: u256); + fn set_approval_for_all(operator: ContractAddress, approved: bool); fn get_approved(token_id: u256) -> ContractAddress; fn is_approved_for_all(owner: ContractAddress, operator: ContractAddress) -> bool; + fn mint(to: ContractAddress, token_id: u256); fn burn(token_id: u256); - fn approve(to: ContractAddress, token_id: u256); - fn set_approval_for_all(operator: ContractAddress, approved: bool); fn transfer_from(from: ContractAddress, to: ContractAddress, token_id: u256); } From afcf0c748401ce919b3c7570b50f2115456a5234 Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 15:03:25 +0200 Subject: [PATCH 09/11] added @0xKubitus changes --- README.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4e6241a..d75ebd4 100644 --- a/README.md +++ b/README.md @@ -78,20 +78,24 @@ Here, we will focus on creating the burn function. 4. Send a token to the Evaluator contract by using the mint function from your deployed function. 5. Call `ex_03_erc721_burn()` to verify the `burn()` function within your contract and receive points. -### Exercise 4 - Approve function (2 points) +### Exercise 4 - Approving a token (2 points) -1. Create the `approve()` function -2. Create the `get_approved()` function for the Evaluator to receive the results back -3. Deploy your contract on testnet -4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +This time, our job is to create the '`approve()` function, which can then be used to give permission to a specific contract address to interact with a specific NFT. + +1. Create the `approve()` function. +2. Create the `get_approved()` function. +3. Deploy your contract on testnet. +4. Call `submit_exercise()` in the evaluator to configure the contract you want to be evaluated. 5. Call `ex_04_erc721_approve()` to verify your contract and receive points. ### Exercise 5 - Approve all function (2 points) -1. Create the `set_approval_for_all()` function -2. Create the `is_approved_for_all()` function for the Evaluator to receive the results back -3. Deploy your contract on testnet -4. Call `submit_exercise()` in the Evaluator to configure the contract you want to be evaluated. +Here we will create the `set_approval_for_all()` function, which can then be used to give permission to a specific contract address to have full permission over our NFT contract. + +1. Create the `set_approval_for_all()` function. +2. Create the `is_approved_for_all()` function. +3. Deploy your contract on testnet. +4. Call `submit_exercise()` in the evaluator to configure the contract you want to be evaluated. 5. Call `ex_05_erc721_approve_for_all()` to verify your contract and receive points. ### Exercise 6 - Transfering a token (2 points) From 082544855ef427195cae6d95db19ec0ea5417b26 Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 16:14:11 +0200 Subject: [PATCH 10/11] update readme --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index d75ebd4..e9329fc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Starknet ERC721 - An Automated Workshop +# Starknet ERC721, Part 1 - An Automated Workshop ## Introduction @@ -44,8 +44,6 @@ Before we begin, make sure to check out the `IERC721.cairo` which is interface f ### Exercise 1 - Deploying and initilizing your ERC721 (2 points) -First exercise of this part is to create your ERC721 Contract and your constructor function. - 1. Create your initial ERC721 contract. You will need the following: 1. a constructor function that takes the `name` and `symbol` as input and then initializes the contract with those inputs 2. a `get_name()` to receive the name of the ERC721 From c475449f12f0019598a84441ccb1c491caa9586b Mon Sep 17 00:00:00 2001 From: robertkodra Date: Tue, 13 Jun 2023 16:18:25 +0200 Subject: [PATCH 11/11] update readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index e9329fc..8421f83 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,6 @@ Enjoy the workshop! If you have any questions, feel free to contact us on [Disco ## Tasks list -Before we begin, make sure to check out the `IERC721.cairo` which is interface for the ERC721. - ### Exercise 1 - Deploying and initilizing your ERC721 (2 points) 1. Create your initial ERC721 contract. You will need the following: