diff --git a/onchain/src/quests/template_quest.cairo b/onchain/src/quests/template_quest.cairo new file mode 100644 index 00000000..733cc096 --- /dev/null +++ b/onchain/src/quests/template_quest.cairo @@ -0,0 +1,67 @@ +use art_peace::templates::interfaces::{ + ITemplateStoreDispatcher, ITemplateStoreDispatcherTrait, ITemplateVerifierDispatcher, + ITemplateVerifierDispatcherTrait, TemplateMetadata +}; + +#[starknet::contract] +pub mod TemplateQuest { + use starknet::{ContractAddress, get_caller_address}; + use art_peace::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait}; + use art_peace::quests::{IQuest, QuestClaimed}; + + #[storage] + struct Storage { + art_peace: IArtPeaceDispatcher, + reward: u32, + claimed: LegacyMap, + } + + + #[abi(embed_v0)] + impl TemplateQuest of IQuest { + fn get_reward(self: @ContractState) -> u32 { + self.reward.read() + } + + fn is_claimable( + self: @ContractState, user: ContractAddress, calldata: Span + ) -> bool { + let art_peace = self.art_peace.read(); + + if self.claimed.read(user) { + return false; + } + + let template_store = ITemplateStoreDispatcher { contract_address: art_peace.contract_address }; + + let template_id = calldata[0]; + + let template = template_store.get_template(template_id); + + if template.creator != user { + return false; + } + + return true; + + } + + fn claim(ref self: ContractState, user: ContractAddress, calldata: Span) -> u32 { + assert( + get_caller_address() == self.art_peace.read().contract_address, + 'Only ArtPeace can claim quests' + ); + // TODO: should we revert if the quest is not claimable? + if !self.is_claimable(user, calldata) { + return 0; + } + + self.claimed.write(user, true); + let reward = self.reward.read(); + self.emit(QuestClaimed { user, reward, calldata }); + + reward + } + } + +} \ No newline at end of file diff --git a/onchain/src/templates/interfaces.cairo b/onchain/src/templates/interfaces.cairo index 2ecb9962..62e4d585 100644 --- a/onchain/src/templates/interfaces.cairo +++ b/onchain/src/templates/interfaces.cairo @@ -7,7 +7,8 @@ pub struct TemplateMetadata { pub width: u128, pub height: u128, pub reward: u256, - pub reward_token: ContractAddress + pub reward_token: ContractAddress, + pub creator: ContractAddress } #[starknet::interface] diff --git a/onchain/src/tests/art_peace.cairo b/onchain/src/tests/art_peace.cairo index 73c10d43..baec2d33 100644 --- a/onchain/src/tests/art_peace.cairo +++ b/onchain/src/tests/art_peace.cairo @@ -21,7 +21,7 @@ use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721Dispatche use snforge_std as snf; use snforge_std::{CheatTarget, ContractClassTrait}; -use starknet::{ContractAddress, contract_address_const, get_contract_address}; +use starknet::{ContractAddress, contract_address_const, get_contract_address, get_caller_address}; const DAY_IN_SECONDS: u64 = consteval_int!(60 * 60 * 24); const WIDTH: u128 = 100; @@ -402,7 +402,7 @@ fn template_full_basic_test() { let template_image = array![1, 2, 3, 4]; let template_hash = compute_template_hash(template_image.span()); let template_metadata = TemplateMetadata { - hash: template_hash, position: 0, width: 2, height: 2, reward: 0, reward_token: erc20_mock, + hash: template_hash, position: 0, width: 2, height: 2, reward: 0, reward_token: erc20_mock, creator: get_caller_address() }; template_store.add_template(template_metadata); @@ -550,6 +550,7 @@ fn deposit_reward_test() { height: 2, reward: reward_amount, reward_token: erc20_mock, + creator: get_caller_address(), }; IERC20Dispatcher { contract_address: erc20_mock }.approve(art_peace_address, reward_amount);