Skip to content

Commit

Permalink
authority quest
Browse files Browse the repository at this point in the history
  • Loading branch information
TAdev0 committed May 1, 2024
1 parent c271dc6 commit ee6816a
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 2 deletions.
4 changes: 3 additions & 1 deletion onchain/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use interfaces::{IArtPeace, IArtPeaceDispatcher, IArtPeaceDispatcherTrait, Pixel


mod quests {
pub mod authority_quest;
pub mod interfaces;
pub mod pixel_quest;
pub mod template_quest;
pub mod unruggable_quest;

use interfaces::{
IQuest, IPixelQuest, IUnruggableQuest, QuestClaimed, IQuestDispatcher,
IQuest, IAuthorityQuest, IPixelQuest, IUnruggableQuest, QuestClaimed, IQuestDispatcher,
IQuestDispatcherTrait, IUnruggableMemecoin, IUnruggableMemecoinDispatcher,
IUnruggableMemecoinDispatcherTrait
};
Expand Down Expand Up @@ -58,6 +59,7 @@ mod tests {
mod art_peace;
mod username_store;
mod template_quest;
mod authority_quest;
pub(crate) mod utils;
}

82 changes: 82 additions & 0 deletions onchain/src/quests/authority_quest.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#[starknet::contract]
pub mod AuthorityQuest {
use core::traits::TryInto;
use starknet::{ContractAddress, get_caller_address};
use art_peace::templates::interfaces::{ITemplateStoreDispatcher, ITemplateStoreDispatcherTrait};
use art_peace::quests::{IAuthorityQuest, IQuest, QuestClaimed};

#[storage]
struct Storage {
art_peace: ContractAddress,
authority: ContractAddress,
reward: u32,
claimable: LegacyMap<ContractAddress, bool>,
claimed: LegacyMap<ContractAddress, bool>,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
QuestClaimed: QuestClaimed,
}


#[derive(Drop, Serde)]
pub struct AuthorityQuestInitParams {
pub art_peace: ContractAddress,
pub authority: ContractAddress,
pub reward: u32,
}

#[constructor]
fn constructor(ref self: ContractState, init_params: AuthorityQuestInitParams) {
self.art_peace.write(init_params.art_peace);
self.authority.write(init_params.authority);
self.reward.write(init_params.reward);
}

#[abi(embed_v0)]
impl AuthorityQuestImpl of IAuthorityQuest<ContractState> {
fn mark_claimable(ref self: ContractState, calldata: Span<felt252>) {
assert(get_caller_address() == self.authority.read(), 'Only authority address allowed');
let mut i = 0;
while i < calldata.len() {
self.claimable.write((*calldata[i]).try_into().unwrap(), true);
i += 1;
}
}
}

#[abi(embed_v0)]
impl AuthorityQuest of IQuest<ContractState> {
fn get_reward(self: @ContractState) -> u32 {
self.reward.read()
}

fn is_claimable(
self: @ContractState, user: ContractAddress, calldata: Span<felt252>
) -> bool {
if self.claimed.read(user) {
return false;
}

if self.claimable.read(user) {
true
} else {
false
}
}

fn claim(ref self: ContractState, user: ContractAddress, calldata: Span<felt252>) -> u32 {
assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests');

assert(self.is_claimable(user, calldata), 'Quest not claimable');

self.claimed.write(user, true);
let reward = self.reward.read();
self.emit(QuestClaimed { user, reward, calldata });

reward
}
}
}
5 changes: 5 additions & 0 deletions onchain/src/quests/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ pub trait IQuest<TContractState> {
fn claim(ref self: TContractState, user: ContractAddress, calldata: Span<felt252>) -> u32;
}

#[starknet::interface]
pub trait IAuthorityQuest<TContractState>{
fn mark_claimable(ref self: TContractState, calldata: Span<felt252>);
}

#[starknet::interface]
pub trait IPixelQuest<TContractState> {
fn is_claimed(self: @TContractState, user: starknet::ContractAddress) -> bool;
Expand Down
2 changes: 1 addition & 1 deletion onchain/src/quests/unruggable_quest.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub mod UnruggableQuest {
fn claim(ref self: ContractState, user: ContractAddress, calldata: Span<felt252>) -> u32 {
assert(get_caller_address() == self.art_peace.read(), 'Only ArtPeace can claim quests');

assert(self.is_claimable(user, calldata), 'quest not claimable');
assert(self.is_claimable(user, calldata), 'Quest not claimable');

self.claimed.write(user, true);
let reward = self.reward.read();
Expand Down
96 changes: 96 additions & 0 deletions onchain/src/tests/authority_quest.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use art_peace::{IArtPeaceDispatcher, IArtPeaceDispatcherTrait};
use art_peace::quests::authority_quest::AuthorityQuest::AuthorityQuestInitParams;
use art_peace::quests::interfaces::{IAuthorityQuestDispatcher, IAuthorityQuestDispatcherTrait};
use art_peace::tests::art_peace::deploy_with_quests_contract;
use art_peace::tests::utils;
use starknet::{ContractAddress, get_caller_address, get_contract_address, contract_address_const};
use snforge_std as snf;
use snforge_std::{declare, CheatTarget, ContractClassTrait};

fn deploy_authority_quest_main() -> ContractAddress {
let authority_quest = declare("AuthorityQuest");
let mut authority_calldata = array![];
AuthorityQuestInitParams { art_peace: utils::ART_PEACE_CONTRACT(), authority: get_contract_address(), reward: 20, }
.serialize(ref authority_calldata);
let main_authority_quest = authority_quest.deploy(@authority_calldata).unwrap();

main_authority_quest
}

#[test]
fn deploy_authority_quest_main_test() {
let main_authority_quest = deploy_authority_quest_main();

let art_peace = IArtPeaceDispatcher {
contract_address: deploy_with_quests_contract(
array![].span(), array![main_authority_quest].span()
)
};

let zero_address = contract_address_const::<0>();

assert!(
art_peace.get_days_quests(0) == array![zero_address, zero_address, zero_address].span(),
"Daily quests were not set correctly"
);
assert!(
art_peace.get_main_quests() == array![main_authority_quest].span(),
"Main quests were not set correctly"
);
}

#[test]
fn authority_quest_test() {
let main_authority_quest = deploy_authority_quest_main();

let art_peace = IArtPeaceDispatcher {
contract_address: deploy_with_quests_contract(
array![].span(), array![main_authority_quest].span()
)
};

let main_authority_quest = IAuthorityQuestDispatcher{contract_address: main_authority_quest};

let calldata: Span<felt252> = array![utils::PLAYER1().try_into().unwrap(), utils::PLAYER2().try_into().unwrap()].span();
main_authority_quest.mark_claimable(calldata);

snf::start_prank(target: CheatTarget::One(art_peace.contract_address), caller_address: utils::PLAYER1());
art_peace.claim_main_quest(0, calldata);

assert!(
art_peace.get_extra_pixels_count() == 20, "Extra pixels are wrong after main quest claim"
);

snf::start_prank(target: CheatTarget::One(art_peace.contract_address), caller_address: utils::PLAYER2());
art_peace.claim_main_quest(0, calldata);

assert!(
art_peace.get_extra_pixels_count() == 20, "Extra pixels are wrong after main quest claim"
);
}

#[test]
#[should_panic(expected: ('Quest not claimable',))]
fn authority_quest_double_claim_test() {
let main_authority_quest = deploy_authority_quest_main();

let art_peace = IArtPeaceDispatcher {
contract_address: deploy_with_quests_contract(
array![].span(), array![main_authority_quest].span()
)
};

let main_authority_quest = IAuthorityQuestDispatcher{contract_address: main_authority_quest};

let calldata: Span<felt252> = array![utils::PLAYER1().try_into().unwrap()].span();
main_authority_quest.mark_claimable(calldata);

snf::start_prank(target: CheatTarget::One(art_peace.contract_address), caller_address: utils::PLAYER1());
art_peace.claim_main_quest(0, calldata);

assert!(
art_peace.get_extra_pixels_count() == 20, "Extra pixels are wrong after main quest claim"
);

art_peace.claim_main_quest(0, calldata);
}

0 comments on commit ee6816a

Please sign in to comment.