Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update to new pattern in cairo2 #5

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandri

[dependencies]
starknet = ">=2.2.0"
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.5.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.7.1" }
openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.7.0" }
22 changes: 11 additions & 11 deletions src/GuildSBT.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
// @notice SBT contract to give out to contributor

use starknet::ContractAddress;
use array::{Array, ArrayTrait, SpanTrait};
use serde::Serde;
use traits::{Into, TryInto};
use array::Array;


#[starknet::interface]
trait IMaster<T> {
Expand All @@ -22,6 +21,7 @@ trait IGuildSBT<TContractState> {
fn tokenURI(self: @TContractState, token_id: u256) -> Span<felt252>;
fn tokenURI_from_contributor(self: @TContractState, contributor: ContractAddress) -> Span<felt252>;
fn get_master(self: @TContractState) -> ContractAddress;
fn get_next_token_id(self: @TContractState) -> u256;
fn get_contribution_tier(self: @TContractState, contributor: ContractAddress) -> u32;
fn get_contribution_levels(self: @TContractState) -> Array<u32>;
fn get_number_of_levels(self: @TContractState) -> u32;
Expand Down Expand Up @@ -143,6 +143,10 @@ mod GuildSBT {
self._master.read()
}

fn get_next_token_id(self: @ContractState) -> u256 {
self._next_token_id.read()
}


fn get_contribution_tier(self: @ContractState, contributor: ContractAddress) -> u32 {
let master = self._master.read();
Expand Down Expand Up @@ -195,13 +199,13 @@ mod GuildSBT {
let balance = erc721_self.balance_of(:account);
assert (balance == 0, 'ALREADY_MINTED');

self._token_type.write(account, token_type);
let master = self._master.read();
let masterDispatcher = IMasterDispatcher { contract_address: master };
let points = masterDispatcher.get_dev_points(account);
let tier = InternalImpl::_get_contribution_tier(@self, points);

assert (tier != 0, 'NOT_ENOUGH_POINTS');
self._token_type.write(account, token_type);
let token_id = self._next_token_id.read();
erc721_self._mint(to: account, token_id: token_id.into());
self._wallet_of_owner.write(account, token_id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered adding events on _wallet_of_owner and _token_type write?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think its necessary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as transfer/mint event take care of _wallet_of_owner update and don't think it is necessary to index _token_type

Expand Down Expand Up @@ -232,10 +236,6 @@ mod GuildSBT {

}





}

#[generate_trait]
Expand All @@ -249,12 +249,12 @@ mod GuildSBT {
let mut current_index = 0_u32;
let contribution_levels = self._contribution_levels.read();
loop {
if (current_index == contribution_levels.len() - 1) {
break true;
if (current_index == contribution_levels.len()) {
break;
}

if (points < *contribution_levels[current_index]) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it be <=?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its correct as per the logic

break true;
break;
}

current_index += 1;
Expand Down
178 changes: 57 additions & 121 deletions src/Master.cairo

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions tests/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod test_deployment;
mod test_migrate_points;
mod test_mint;
mod test_update_contribution_points;
mod utils;
17 changes: 5 additions & 12 deletions tests/test_deployment.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use starknet::ClassHash;
use traits::TryInto;
use option::OptionTrait;
use snforge_std::{ declare, ContractClassTrait };
use tests::utils::{ deployer_addr, user1};
use tests::utils::{ deployer_addr, user1, URI};


#[starknet::interface]
Expand All @@ -25,15 +25,6 @@ trait IGuildSBT<T> {

}

fn URI() -> Span<felt252> {
let mut uri = ArrayTrait::new();

uri.append('api.jediswap/');
uri.append('guildSBT/');
uri.append('dev/');

uri.span()
}

#[test]
fn test_deployment_master_guildSBT() {
Expand Down Expand Up @@ -79,8 +70,10 @@ fn test_deployment_master_guildSBT() {
assert(symbol == 'JEDI-DEV', 'Invalid symbol');

let baseURI: Span<felt252> = guildSBT_dispatcher.baseURI();
// TODO: compare span with felt252
// assert(baseURI == 'api.jediswap/guildSBT/dev/', 'Invalid base uri');
assert(*baseURI[0] == 'api.jediswap/', 'Invlalid item 0');
assert(*baseURI[1] == 'guildSBT/', 'Invlalid item 1');
assert(*baseURI[2] == 'dev/', 'Invlalid item 2');
assert(baseURI.len() == 3, 'should be 3');

let owner = guildSBT_dispatcher.owner();
assert(owner == deployer_addr(), 'Invalid Owner');
Expand Down
116 changes: 98 additions & 18 deletions tests/test_migrate_points.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ use traits::TryInto;
use option::OptionTrait;
use snforge_std::{ declare, ContractClassTrait, ContractClass, start_warp, start_prank, stop_prank,
spy_events, SpyOn, EventSpy, EventFetcher, Event, EventAssertions };
use tests::utils::{ deployer_addr, user1, user2, user3, user4};
use tests::utils::{ deployer_addr, user1, user2, user3, user4, URI};
use contributor_SBT2_0::Master::MonthlyContribution;
use contributor_SBT2_0::Master::Contribution;

#[starknet::interface]
trait IMaster<TContractState> {
fn get_last_update_id(self: @TContractState) -> u32;
fn get_dev_points(self: @TContractState, contributor: ContractAddress) -> u32;
fn get_contibutions_points(self: @TContractState, contributor: ContractAddress) -> Contribution;
fn get_contributions_points(self: @TContractState, contributor: ContractAddress) -> Contribution;

fn update_contibutions(ref self: TContractState, month_id: u32, contributions: Array::<MonthlyContribution>);
fn migrate_points_initiated_by_DAO(ref self: TContractState, old_addresses: Array::<ContractAddress>, new_addresses: Array::<ContractAddress> );
Expand All @@ -36,15 +36,7 @@ trait IGuildSBT<TContractState> {
}


fn URI() -> Span<felt252> {
let mut uri = ArrayTrait::new();

uri.append('api.jediswap/');
uri.append('guildSBT/');
uri.append('dev/');

uri.span()
}

fn deploy_contracts_and_initialise() -> (ContractAddress, ContractAddress, ContractAddress, ContractAddress, ContractAddress, ContractAddress) {
let mut master_constructor_calldata = Default::default();
Expand Down Expand Up @@ -83,11 +75,10 @@ fn deploy_contracts_and_initialise() -> (ContractAddress, ContractAddress, Contr
master_dispatcher.initialise(dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address);
stop_prank(master_address);



(master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address)
}


fn update_contribution_and_minting_sbt(master_address: ContractAddress, dev_guildSBT_address: ContractAddress, design_guildSBT_address: ContractAddress, marcom_guildSBT_address: ContractAddress, problem_solving_guildSBT_address: ContractAddress, research_guildSBT_address: ContractAddress) -> (MonthlyContribution, MonthlyContribution) {
let master_dispatcher = IMasterDispatcher { contract_address: master_address };

Expand Down Expand Up @@ -171,14 +162,14 @@ fn test_migrate_points_initiated_by_DAO() {


// verifying points are successfully migrated
let user3_contribution: Contribution = master_dispatcher.get_contibutions_points(user3());
let user3_contribution: Contribution = master_dispatcher.get_contributions_points(user3());
assert(user3_contribution.dev == user1_contribution.dev, '');
assert(user3_contribution.design == user1_contribution.design, '');
assert(user3_contribution.marcom == user1_contribution.marcom, '');
assert(user3_contribution.problem_solving == user1_contribution.problem_solving, '');
assert(user3_contribution.research == user1_contribution.research, '');

let user4_contribution: Contribution = master_dispatcher.get_contibutions_points(user4());
let user4_contribution: Contribution = master_dispatcher.get_contributions_points(user4());
assert(user4_contribution.dev == user2_contribution.dev, '');
assert(user4_contribution.design == user2_contribution.design, '');
assert(user4_contribution.marcom == user2_contribution.marcom, '');
Expand All @@ -187,14 +178,14 @@ fn test_migrate_points_initiated_by_DAO() {


// verfying points of old addresses is resetted to zero
let user1_contribution_updated: Contribution = master_dispatcher.get_contibutions_points(user1());
let user1_contribution_updated: Contribution = master_dispatcher.get_contributions_points(user1());
assert(user1_contribution_updated.dev == 0, '');
assert(user1_contribution_updated.design == 0, '');
assert(user1_contribution_updated.marcom == 0, '');
assert(user1_contribution_updated.problem_solving == 0, '');
assert(user1_contribution_updated.research == 0, '');

let user2_contribution_updated: Contribution = master_dispatcher.get_contibutions_points(user2());
let user2_contribution_updated: Contribution = master_dispatcher.get_contributions_points(user2());
assert(user2_contribution_updated.dev == 0, '');
assert(user2_contribution_updated.design == 0, '');
assert(user2_contribution_updated.marcom == 0, '');
Expand Down Expand Up @@ -234,6 +225,66 @@ fn test_migrate_points_initiated_by_DAO() {

}

#[test]
#[should_panic(expected: ('Caller is not the owner', ))]
fn test_migrate_points_initiated_by_DAO_not_owner() {
let (master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address) = deploy_contracts_and_initialise();
let (user1_contribution, user2_contribution) = update_contribution_and_minting_sbt(master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address);

let master_dispatcher = IMasterDispatcher { contract_address: master_address };

// migrating user1 -> user3 and user2 -> user4
let mut old_addresses = ArrayTrait::new();
old_addresses.append(user1());
old_addresses.append(user2());

let mut new_addresses = ArrayTrait::new();
new_addresses.append(user3());
new_addresses.append(user4());

let mut spy = spy_events(SpyOn::One(master_address));

start_prank(master_address, user1());
master_dispatcher.migrate_points_initiated_by_DAO(old_addresses, new_addresses);
yashm001 marked this conversation as resolved.
Show resolved Hide resolved
stop_prank(master_address);

let mut event_data_1 = Default::default();
Serde::serialize(@user1(), ref event_data_1);
Serde::serialize(@user3(), ref event_data_1);
spy.assert_emitted(@array![
Event { from: master_address, name: 'Migrated', keys: array![], data: event_data_1 }
]);

let mut event_data_2 = Default::default();
Serde::serialize(@user2(), ref event_data_2);
Serde::serialize(@user4(), ref event_data_2);
spy.assert_emitted(@array![
Event { from: master_address, name: 'Migrated', keys: array![], data: event_data_2 }
]);

}

#[test]
#[should_panic(expected: ('INVALID_INPUTS', ))]
fn test_migrate_points_initiated_by_DAO_length_mismatch() {
let (master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address) = deploy_contracts_and_initialise();
let (user1_contribution, user2_contribution) = update_contribution_and_minting_sbt(master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address);

let master_dispatcher = IMasterDispatcher { contract_address: master_address };

// migrating user1 -> user3 and user2 -> X (length mismatch)
let mut old_addresses = ArrayTrait::new();
old_addresses.append(user1());
old_addresses.append(user2());

let mut new_addresses = ArrayTrait::new();
new_addresses.append(user3());

start_prank(master_address, deployer_addr());
master_dispatcher.migrate_points_initiated_by_DAO(old_addresses, new_addresses);
stop_prank(master_address);
}

#[test]
fn test_migrate_points_initiated_by_holder() {
let (master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address) = deploy_contracts_and_initialise();
Expand All @@ -248,27 +299,42 @@ fn test_migrate_points_initiated_by_holder() {
let user_1_dev_token_id = dev_guildSBT_dispatcher.wallet_of_owner(user1());
let user_1_design_token_id = design_guildSBT_dispatcher.wallet_of_owner(user1());

let mut spy = spy_events(SpyOn::One(master_address));

// initiating migration request
start_prank(master_address, user1());
master_dispatcher.migrate_points_initiated_by_holder(user3());
stop_prank(master_address);

let mut event_data_1 = Default::default();
Serde::serialize(@user1(), ref event_data_1);
Serde::serialize(@user3(), ref event_data_1);
spy.assert_emitted(@array![
Event { from: master_address, name: 'MigrationQueued', keys: array![], data: event_data_1 }
]);

// executing migration (by DAO)
start_prank(master_address, deployer_addr());
master_dispatcher.execute_migrate_points_initiated_by_holder(user1(), user3());
stop_prank(master_address);

let mut event_data_2 = Default::default();
Serde::serialize(@user1(), ref event_data_2);
Serde::serialize(@user3(), ref event_data_2);
spy.assert_emitted(@array![
Event { from: master_address, name: 'Migrated', keys: array![], data: event_data_2 }
]);

// verifying points are successfully migrated
let user3_contribution: Contribution = master_dispatcher.get_contibutions_points(user3());
let user3_contribution: Contribution = master_dispatcher.get_contributions_points(user3());
assert(user3_contribution.dev == user1_contribution.dev, '');
assert(user3_contribution.design == user1_contribution.design, '');
assert(user3_contribution.marcom == user1_contribution.marcom, '');
assert(user3_contribution.problem_solving == user1_contribution.problem_solving, '');
assert(user3_contribution.research == user1_contribution.research, '');

// verfying points of old addresses is resetted to zero
let user1_contribution_updated: Contribution = master_dispatcher.get_contibutions_points(user1());
let user1_contribution_updated: Contribution = master_dispatcher.get_contributions_points(user1());
assert(user1_contribution_updated.dev == 0, '');
assert(user1_contribution_updated.design == 0, '');
assert(user1_contribution_updated.marcom == 0, '');
Expand All @@ -295,4 +361,18 @@ fn test_migrate_points_initiated_by_holder() {
assert(user_3_design_token_id == user_1_design_token_id, '');


}

#[should_panic(expected: ('NOT_QUEUED', ))]
#[test]
fn test_execute_migrate_points_without_initiating() {
let (master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address) = deploy_contracts_and_initialise();
let (user1_contribution, user2_contribution) = update_contribution_and_minting_sbt(master_address, dev_guildSBT_address, design_guildSBT_address, marcom_guildSBT_address, problem_solving_guildSBT_address, research_guildSBT_address);

let master_dispatcher = IMasterDispatcher { contract_address: master_address };

// executing migration (by DAO) without initiated by holder.
start_prank(master_address, deployer_addr());
master_dispatcher.execute_migrate_points_initiated_by_holder(user1(), user3());
stop_prank(master_address);
}
Loading