From 5c14814d8198af4e4fb6ed8113df1dfd192564b9 Mon Sep 17 00:00:00 2001 From: Tristan <122918260+TAdev0@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:19:43 +0200 Subject: [PATCH] Few improvements (#33) * few improvements * Docker snfoundry version --------- Co-authored-by: Brandon Roberts --- .tool-versions | 2 +- backend/Dockerfile | 2 +- onchain/Dockerfile | 2 +- onchain/Scarb.lock | 4 +- onchain/Scarb.toml | 3 +- onchain/src/art_peace.cairo | 39 +++++++++++-------- onchain/src/interface.cairo | 4 +- onchain/src/lib.cairo | 8 ++-- .../{interface.cairo => interfaces.cairo} | 8 ++++ onchain/src/quests/pixel_quest.cairo | 31 +++++++-------- onchain/src/templates/component.cairo | 13 ++++--- onchain/src/templates/interface.cairo | 12 +++--- onchain/src/tests/art_peace.cairo | 7 +++- 13 files changed, 76 insertions(+), 59 deletions(-) rename onchain/src/quests/{interface.cairo => interfaces.cairo} (66%) diff --git a/.tool-versions b/.tool-versions index 6594d5c8..835a9946 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ scarb 2.6.3 -starknet-foundry 0.20.0 +starknet-foundry 0.21.0 diff --git a/backend/Dockerfile b/backend/Dockerfile index 20a65002..8570c68b 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -9,7 +9,7 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/instal RUN curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | bash # TODO: Source not working properly & requiring manual /root/.local/bin/ paths RUN source /root/.profile -RUN /bin/bash /root/.local/bin/snfoundryup --version 0.20.0 +RUN /bin/bash /root/.local/bin/snfoundryup --version 0.21.0 # Copy over the configs WORKDIR /configs diff --git a/onchain/Dockerfile b/onchain/Dockerfile index 61d953b6..85840c4e 100644 --- a/onchain/Dockerfile +++ b/onchain/Dockerfile @@ -8,7 +8,7 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/instal RUN curl -L https://raw.githubusercontent.com/foundry-rs/starknet-foundry/master/scripts/install.sh | bash # TODO: Source not working properly & requiring manual /root/.local/bin/ paths RUN source /root/.bashrc -RUN /bin/bash /root/.local/bin/snfoundryup --version 0.20.0 +RUN /bin/bash /root/.local/bin/snfoundryup --version 0.21.0 # TODO: build container? diff --git a/onchain/Scarb.lock b/onchain/Scarb.lock index bb1ac929..576c9446 100644 --- a/onchain/Scarb.lock +++ b/onchain/Scarb.lock @@ -10,5 +10,5 @@ dependencies = [ [[package]] name = "snforge_std" -version = "0.20.0" -source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.20.0#423eecf7847469e353258321274394b9155d24eb" +version = "0.21.0" +source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.21.0#2996b8c1dd66b2715fc67e69578089f278a46790" diff --git a/onchain/Scarb.toml b/onchain/Scarb.toml index 99ed1283..28b58fd0 100644 --- a/onchain/Scarb.toml +++ b/onchain/Scarb.toml @@ -1,11 +1,12 @@ [package] name = "art_peace" version = "0.1.0" +edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] -snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.20.0" } +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.21.0" } starknet = "2.6.3" [scripts] diff --git a/onchain/src/art_peace.cairo b/onchain/src/art_peace.cairo index 2fffa74f..92f65449 100644 --- a/onchain/src/art_peace.cairo +++ b/onchain/src/art_peace.cairo @@ -2,9 +2,9 @@ pub mod ArtPeace { use starknet::ContractAddress; use art_peace::{IArtPeace, Pixel}; - use art_peace::quests::{IQuestDispatcher, IQuestDispatcherTrait}; + use art_peace::quests::interfaces::{IQuestDispatcher, IQuestDispatcherTrait}; use art_peace::templates::component::TemplateStoreComponent; - use art_peace::templates::{ITemplateVerifier, TemplateMetadata}; + use art_peace::templates::interface::{ITemplateVerifier, TemplateMetadata}; component!(path: TemplateStoreComponent, storage: templates, event: TemplateEvent); @@ -139,6 +139,7 @@ pub mod ArtPeace { fn get_pixel_xy(self: @ContractState, x: u128, y: u128) -> Pixel { let pos = x + y * self.canvas_width.read(); + self.canvas.read(pos) } @@ -156,13 +157,13 @@ pub mod ArtPeace { fn place_pixel(ref self: ContractState, pos: u128, color: u8) { let now = starknet::get_block_timestamp(); - assert!(now <= self.end_time.read()); - assert!(pos < self.total_pixels.read()); - assert!(color < self.color_count.read()); + assert(now <= self.end_time.read(), ''); + assert(pos < self.total_pixels.read(), ''); + assert(color < self.color_count.read(), ''); // TODO: Use sender not caller? let caller = starknet::get_caller_address(); // TODO: Only if the user has placed a pixel before? - assert!(now - self.last_placed_time.read(caller) >= self.time_between_pixels.read()); + assert(now - self.last_placed_time.read(caller) >= self.time_between_pixels.read(), ''); let pixel = Pixel { color, owner: caller }; self.canvas.write(pos, pixel); self.last_placed_time.write(caller, now); @@ -182,12 +183,12 @@ pub mod ArtPeace { fn place_extra_pixels(ref self: ContractState, positions: Array, colors: Array) { let now = starknet::get_block_timestamp(); - assert!(now <= self.end_time.read()); + assert(now <= self.end_time.read(), ''); let pixel_count = positions.len(); - assert!(pixel_count == colors.len()); + assert(pixel_count == colors.len(), ''); let caller = starknet::get_caller_address(); let extra_pixels = self.extra_pixels.read(caller); - assert!(pixel_count <= extra_pixels); + assert(pixel_count <= extra_pixels, ''); let color_palette_count = self.color_count.read(); let total_pixels = self.total_pixels.read(); let day = self.day_index.read(); @@ -195,8 +196,8 @@ pub mod ArtPeace { while i < pixel_count { let pos = *positions.at(i); let color = *colors.at(i); - assert!(pos < total_pixels); - assert!(color < color_palette_count); + assert(pos < total_pixels, ''); + assert(color < color_palette_count, ''); let pixel = Pixel { color, owner: caller }; self.canvas.write(pos, pixel); self @@ -242,6 +243,7 @@ pub mod ArtPeace { colors.append(self.color_palette.read(i)); i += 1; }; + colors } @@ -285,6 +287,7 @@ pub mod ArtPeace { quests.append(self.daily_quests.read((day_index, i))); i += 1; }; + quests.span() } @@ -297,6 +300,7 @@ pub mod ArtPeace { quests.append(self.daily_quests.read((day, i))); i += 1; }; + quests.span() } @@ -316,6 +320,7 @@ pub mod ArtPeace { quests.append(self.main_quests.read(i)); i += 1; }; + quests.span() } @@ -323,7 +328,7 @@ pub mod ArtPeace { ref self: ContractState, day_index: u32, quest_id: u32, calldata: Span ) { let now = starknet::get_block_timestamp(); - assert!(now <= self.end_time.read()); + assert(now <= self.end_time.read(), ''); // TODO: Only allow to claim the quest of the current day let quest = self.daily_quests.read((day_index, quest_id)); let user = starknet::get_caller_address(); @@ -340,7 +345,7 @@ pub mod ArtPeace { fn claim_today_quest(ref self: ContractState, quest_id: u32, calldata: Span) { let now = starknet::get_block_timestamp(); - assert!(now <= self.end_time.read()); + assert(now <= self.end_time.read(), ''); let quest = self.daily_quests.read((self.day_index.read(), quest_id)); let user = starknet::get_caller_address(); let reward = IQuestDispatcher { contract_address: quest }.claim(user, calldata); @@ -356,7 +361,7 @@ pub mod ArtPeace { fn claim_main_quest(ref self: ContractState, quest_id: u32, calldata: Span) { let now = starknet::get_block_timestamp(); - assert!(now <= self.end_time.read()); + assert(now <= self.end_time.read(), ''); let quest = self.main_quests.read(quest_id); let user = starknet::get_caller_address(); let reward = IQuestDispatcher { contract_address: quest }.claim(user, calldata); @@ -383,6 +388,7 @@ pub mod ArtPeace { }; i += 1; }; + total } @@ -396,6 +402,7 @@ pub mod ArtPeace { total += self.user_pixels_placed.read((day, user, i)); i += 1; }; + total } @@ -410,8 +417,8 @@ pub mod ArtPeace { impl ArtPeaceTemplateVerifier of ITemplateVerifier { // TODO: Check template function fn complete_template(ref self: ContractState, template_id: u32, template_image: Span) { - assert!(template_id < self.get_templates_count()); - assert!(!self.is_template_complete(template_id)); + assert(template_id < self.get_templates_count(), ''); + assert(!self.is_template_complete(template_id), ''); // TODO: ensure template_image matches the template size & hash let template_metadata: TemplateMetadata = self.get_template(template_id); let non_zero_width: core::zeroable::NonZero:: = template_metadata diff --git a/onchain/src/interface.cairo b/onchain/src/interface.cairo index d0c5040f..6e73f926 100644 --- a/onchain/src/interface.cairo +++ b/onchain/src/interface.cairo @@ -1,9 +1,9 @@ #[derive(Drop, Serde, starknet::Store)] pub struct Pixel { // Color index in the palette - color: u8, + pub color: u8, // The person that placed the pixel - owner: starknet::ContractAddress, + pub owner: starknet::ContractAddress, } // TODO: Tests for all diff --git a/onchain/src/lib.cairo b/onchain/src/lib.cairo index a49dc556..d04c0c45 100644 --- a/onchain/src/lib.cairo +++ b/onchain/src/lib.cairo @@ -4,15 +4,15 @@ use art_peace::ArtPeace; use interface::{IArtPeace, IArtPeaceDispatcher, IArtPeaceDispatcherTrait, Pixel}; mod quests { - pub mod interface; - mod pixel_quest; + pub mod interfaces; + pub mod pixel_quest; - use interface::{IQuest, QuestClaimed, IQuestDispatcher, IQuestDispatcherTrait}; + use interfaces::{IQuest, IPixelQuest, QuestClaimed, IQuestDispatcher, IQuestDispatcherTrait}; } mod templates { pub mod interface; - mod component; + pub mod component; use interface::{ TemplateMetadata, ITemplateVerifier, ITemplateStoreDispatcher, diff --git a/onchain/src/quests/interface.cairo b/onchain/src/quests/interfaces.cairo similarity index 66% rename from onchain/src/quests/interface.cairo rename to onchain/src/quests/interfaces.cairo index 41b5f21f..ad576d9f 100644 --- a/onchain/src/quests/interface.cairo +++ b/onchain/src/quests/interfaces.cairo @@ -16,3 +16,11 @@ pub trait IQuest { // Claim the quest. fn claim(ref self: TContractState, user: ContractAddress, calldata: Span) -> u32; } + +#[starknet::interface] +pub trait IPixelQuest { + fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; + fn get_pixels_needed(self: @TContractState) -> u32; + fn is_daily(self: @TContractState) -> bool; + fn claim_day(self: @TContractState) -> u32; +} diff --git a/onchain/src/quests/pixel_quest.cairo b/onchain/src/quests/pixel_quest.cairo index d6499d28..425c4087 100644 --- a/onchain/src/quests/pixel_quest.cairo +++ b/onchain/src/quests/pixel_quest.cairo @@ -1,17 +1,8 @@ -#[starknet::interface] -trait IPixelQuest { - fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool; - fn get_pixels_needed(self: @TContractState) -> u32; - fn is_daily(self: @TContractState) -> bool; - fn claim_day(self: @TContractState) -> u32; -} - #[starknet::contract] mod PixelQuest { use starknet::{ContractAddress, get_caller_address}; use art_peace::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; - use art_peace::quests::{IQuest, QuestClaimed}; - use super::IPixelQuest; + use art_peace::quests::{IQuest, IPixelQuest, QuestClaimed}; #[storage] struct Storage { @@ -49,26 +40,26 @@ mod PixelQuest { #[abi(embed_v0)] impl PixelQuestImpl of IPixelQuest { fn is_claimed(self: @ContractState, user: ContractAddress) -> bool { - return self.claimed.read(user); + self.claimed.read(user) } fn get_pixels_needed(self: @ContractState) -> u32 { - return self.pixels_needed.read(); + self.pixels_needed.read() } fn is_daily(self: @ContractState) -> bool { - return self.is_daily.read(); + self.is_daily.read() } fn claim_day(self: @ContractState) -> u32 { - return self.claim_day.read(); + self.claim_day.read() } } #[abi(embed_v0)] impl PixelQuest of IQuest { fn get_reward(self: @ContractState) -> u32 { - return self.reward.read(); + self.reward.read() } fn is_claimable( @@ -78,6 +69,7 @@ mod PixelQuest { if self.claimed.read(user) { return false; } + if self.is_daily.read() { // Daily Pixel Quest let day = art_peace.get_day(); @@ -85,11 +77,13 @@ mod PixelQuest { return false; } let placement_count = art_peace.get_user_pixels_placed_day(user, day); - return placement_count >= self.pixels_needed.read(); + + placement_count >= self.pixels_needed.read() } else { // Main Pixel Quest let placement_count = art_peace.get_user_pixels_placed(user); - return placement_count >= self.pixels_needed.read(); + + placement_count >= self.pixels_needed.read() } } @@ -105,7 +99,8 @@ mod PixelQuest { self.claimed.write(user, true); let reward = self.reward.read(); self.emit(QuestClaimed { user, reward, calldata }); - return reward; + + reward } } } diff --git a/onchain/src/templates/component.cairo b/onchain/src/templates/component.cairo index f783e886..e8f658fa 100644 --- a/onchain/src/templates/component.cairo +++ b/onchain/src/templates/component.cairo @@ -1,5 +1,5 @@ #[starknet::component] -mod TemplateStoreComponent { +pub mod TemplateStoreComponent { use art_peace::templates::interface::{ITemplateStore, TemplateMetadata}; #[storage] @@ -13,7 +13,7 @@ mod TemplateStoreComponent { #[event] #[derive(Drop, starknet::Event)] - enum Event { + pub enum Event { TemplateAdded: TemplateAdded, TemplateCompleted: TemplateCompleted, } @@ -37,18 +37,19 @@ mod TemplateStoreComponent { TContractState, +HasComponent > of ITemplateStore> { fn get_templates_count(self: @ComponentState) -> u32 { - return self.templates_count.read(); + self.templates_count.read() } fn get_template( self: @ComponentState, template_id: u32 ) -> TemplateMetadata { - return self.templates.read(template_id); + self.templates.read(template_id) } fn get_template_hash(self: @ComponentState, template_id: u32) -> felt252 { let metadata: TemplateMetadata = self.templates.read(template_id); - return metadata.hash; + + metadata.hash } // TODO: Return idx of the template? @@ -62,7 +63,7 @@ mod TemplateStoreComponent { } fn is_template_complete(self: @ComponentState, template_id: u32) -> bool { - return self.completed_templates.read(template_id); + self.completed_templates.read(template_id) } } } diff --git a/onchain/src/templates/interface.cairo b/onchain/src/templates/interface.cairo index 55c1b66d..44b9d7d1 100644 --- a/onchain/src/templates/interface.cairo +++ b/onchain/src/templates/interface.cairo @@ -1,11 +1,11 @@ #[derive(Drop, Copy, Serde, starknet::Store)] pub struct TemplateMetadata { - hash: felt252, - position: u128, - width: u128, - height: u128, - reward: u256, - reward_token: starknet::ContractAddress + pub hash: felt252, + pub position: u128, + pub width: u128, + pub height: u128, + pub reward: u256, + pub reward_token: starknet::ContractAddress } #[starknet::interface] diff --git a/onchain/src/tests/art_peace.cairo b/onchain/src/tests/art_peace.cairo index a707423c..8b21f2b3 100644 --- a/onchain/src/tests/art_peace.cairo +++ b/onchain/src/tests/art_peace.cairo @@ -1,6 +1,6 @@ use art_peace::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; use art_peace::ArtPeace::InitParams; -use art_peace::templates::{ +use art_peace::templates::interface::{ ITemplateStoreDispatcher, ITemplateStoreDispatcherTrait, ITemplateVerifierDispatcher, ITemplateVerifierDispatcherTrait, TemplateMetadata }; @@ -53,6 +53,7 @@ fn deploy_contract() -> ContractAddress { .serialize(ref calldata); let contract_addr = contract.deploy_at(@calldata, ART_PEACE_CONTRACT()).unwrap(); snf::start_warp(CheatTarget::One(contract_addr), TIME_BETWEEN_PIXELS); + contract_addr } @@ -86,18 +87,21 @@ fn deploy_with_quests_contract( .serialize(ref calldata); let contract_addr = contract.deploy_at(@calldata, ART_PEACE_CONTRACT()).unwrap(); snf::start_warp(CheatTarget::One(contract_addr), TIME_BETWEEN_PIXELS); + contract_addr } fn deploy_pixel_quest_daily(pixel_quest: snf::ContractClass) -> ContractAddress { // art_peace, reward, pixels_needed, is_daily, claim_day let mut calldata: Array = array![ART_PEACE_CONTRACT().into(), 10, 3, 1, 0]; + pixel_quest.deploy(@calldata).unwrap() } fn deploy_pixel_quest_main(pixel_quest: snf::ContractClass) -> ContractAddress { // art_peace, reward, pixels_needed, is_daily, claim_day let mut calldata: Array = array![ART_PEACE_CONTRACT().into(), 20, 4, 0, 0]; + pixel_quest.deploy(@calldata).unwrap() } @@ -118,6 +122,7 @@ fn compute_template_hash(template: Span) -> felt252 { hasher = hasher.update_with(*template.at(i)); i += 1; }; + hasher.finalize() }