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

Change claim types #89

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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 .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:
jobs:
contracts:
name: Contracts
uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@v3.3.1
uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@v4.2.1
with:
rust-toolchain: stable
enable-contracts-size-report: false
Expand Down
6 changes: 3 additions & 3 deletions launchpad-common/src/common_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub trait CommonEventsModule {
fn emit_refund_ticket_payment_event(
&self,
tickets_refunded: usize,
token_payment: EgldOrEsdtTokenPayment<Self::Api>,
token_payment: EgldOrEsdtTokenPayment,
) {
let user = self.blockchain().get_caller();
let block = self.blockchain().get_block_nonce();
Expand All @@ -69,7 +69,7 @@ pub trait CommonEventsModule {
)
}

fn emit_set_ticket_price_event(&self, ticket_price: EgldOrEsdtTokenPayment<Self::Api>) {
fn emit_set_ticket_price_event(&self, ticket_price: EgldOrEsdtTokenPayment) {
let user = self.blockchain().get_caller();
let block = self.blockchain().get_block_nonce();
let epoch = self.blockchain().get_block_epoch();
Expand All @@ -91,7 +91,7 @@ pub trait CommonEventsModule {
tickets_confirmed: usize,
total_confirmed: usize,
total_tickets: usize,
token_payment: EgldOrEsdtTokenPayment<Self::Api>,
token_payment: EgldOrEsdtTokenPayment,
) {
let user = self.blockchain().get_caller();
let block = self.blockchain().get_block_nonce();
Expand Down
2 changes: 1 addition & 1 deletion launchpad-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub trait LaunchpadMain:
"Launchpad token must be different from ticket payment token"
);
}

self.launchpad_token_id().set(&launchpad_token_id);

self.try_set_launchpad_tokens_per_winning_ticket(&launchpad_tokens_per_winning_ticket);
Expand Down
4 changes: 2 additions & 2 deletions launchpad-common/src/token_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub trait TokenSendModule: crate::config::ConfigModule + common_events::CommonEv
}

fn send_launchpad_tokens<
SendLaunchpadTokensFn: Fn(&Self, &ManagedAddress, &EsdtTokenPayment<Self::Api>),
SendLaunchpadTokensFn: Fn(&Self, &ManagedAddress, &EsdtTokenPayment),
>(
&self,
address: &ManagedAddress,
Expand All @@ -48,7 +48,7 @@ pub trait TokenSendModule: crate::config::ConfigModule + common_events::CommonEv
fn default_send_launchpad_tokens_fn(
&self,
address: &ManagedAddress,
payment: &EsdtTokenPayment<Self::Api>,
payment: &EsdtTokenPayment,
) {
self.send().direct_esdt(
address,
Expand Down
124 changes: 96 additions & 28 deletions launchpad-common/src/user_interactions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
multiversx_sc::imports!();
multiversx_sc::derive_imports!();

use crate::{
config::TokenAmountPair,
launch_stage::LaunchStage,
tickets::{TicketRange, WINNING_TICKET},
};

#[derive(TypeAbi, TopEncode, TopDecode)]
pub enum ClaimType {
None,
RefundedTickets,
All,
}

pub struct ClaimRefundedTicketsResultType<M: ManagedTypeApi> {
pub winning_ticket_ids: ManagedVec<M, usize>,
}

use crate::{config::TokenAmountPair, tickets::WINNING_TICKET};
pub struct ClaimLaunchpadTokensResultType {
pub nr_redeemable_tickets: usize,
}

#[multiversx_sc::module]
pub trait UserInteractionsModule:
Expand Down Expand Up @@ -58,55 +78,103 @@ pub trait UserInteractionsModule:
);
}

fn claim_launchpad_tokens<
SendLaunchpadTokensFn: Fn(&Self, &ManagedAddress, &EsdtTokenPayment<Self::Api>),
fn claim_refunded_tickets_and_launchpad_tokens<
SendLaunchpadTokensFn: Fn(&Self, &ManagedAddress, &EsdtTokenPayment),
>(
&self,
send_fn: SendLaunchpadTokensFn,
) {
self.require_claim_period();
) -> ClaimLaunchpadTokensResultType {
let winning_ticket_ids = self.claim_refunded_tickets().winning_ticket_ids;
self.claim_launchpad_tokens(winning_ticket_ids, send_fn)
}

fn claim_refunded_tickets(&self) -> ClaimRefundedTicketsResultType<Self::Api> {
let flags = self.flags().get();
require!(
flags.were_winners_selected && flags.was_additional_step_completed,
"Not in claim period"
);

let caller = self.blockchain().get_caller();
require!(!self.has_user_claimed(&caller), "Already claimed");
let claim_status_mapper = self.claimed_tokens(&caller);
let claim_status = claim_status_mapper.get();
match claim_status {
ClaimType::None => {}
ClaimType::RefundedTickets => {
let ticket_range = self.try_get_ticket_range(&caller);
let winning_ticket_ids = self.get_winning_ticket_ids(&ticket_range);

return ClaimRefundedTicketsResultType { winning_ticket_ids };
}
ClaimType::All => sc_panic!("Already claimed"),
};

let ticket_range = self.try_get_ticket_range(&caller);
let winning_ticket_ids = self.get_winning_ticket_ids(&ticket_range);
let nr_redeemable_tickets = winning_ticket_ids.len();
if nr_redeemable_tickets > 0 {
self.nr_winning_tickets()
.update(|nr_winning_tickets| *nr_winning_tickets -= nr_redeemable_tickets);
}

claim_status_mapper.set(ClaimType::RefundedTickets);

let nr_confirmed_tickets = self.nr_confirmed_tickets(&caller).get();
let mut nr_redeemable_tickets = 0;
let nr_tickets_to_refund = nr_confirmed_tickets - nr_redeemable_tickets;
self.refund_ticket_payment(&caller, nr_tickets_to_refund);

for ticket_id in ticket_range.first_id..=ticket_range.last_id {
let ticket_status = self.ticket_status(ticket_id).get();
if ticket_status == WINNING_TICKET {
self.ticket_status(ticket_id).clear();
ClaimRefundedTicketsResultType { winning_ticket_ids }
}

nr_redeemable_tickets += 1;
}
fn claim_launchpad_tokens<
SendLaunchpadTokensFn: Fn(&Self, &ManagedAddress, &EsdtTokenPayment),
>(
&self,
winning_ticket_ids: ManagedVec<usize>,
send_fn: SendLaunchpadTokensFn,
) -> ClaimLaunchpadTokensResultType {
if self.get_launch_stage() != LaunchStage::Claim {
return ClaimLaunchpadTokensResultType {
nr_redeemable_tickets: 0,
};
}

self.ticket_pos_to_id(ticket_id).clear();
let caller = self.blockchain().get_caller();
let ticket_range = self.try_get_ticket_range(&caller);

for ticket_id in &winning_ticket_ids {
self.ticket_status(ticket_id).clear();
}

self.nr_confirmed_tickets(&caller).clear();
self.ticket_range_for_address(&caller).clear();
self.ticket_batch(ticket_range.first_id).clear();

if nr_redeemable_tickets > 0 {
self.nr_winning_tickets()
.update(|nr_winning_tickets| *nr_winning_tickets -= nr_redeemable_tickets);
}

self.claim_list().add(&caller);
self.claimed_tokens(&caller).set(ClaimType::All);

let nr_tickets_to_refund = nr_confirmed_tickets - nr_redeemable_tickets;
self.refund_ticket_payment(&caller, nr_tickets_to_refund);
let nr_redeemable_tickets = winning_ticket_ids.len();
self.send_launchpad_tokens(&caller, nr_redeemable_tickets, send_fn);
}

#[view(hasUserClaimedTokens)]
fn has_user_claimed(&self, address: &ManagedAddress) -> bool {
self.claim_list().contains(address)
ClaimLaunchpadTokensResultType {
nr_redeemable_tickets,
}
}

// flags
fn get_winning_ticket_ids(&self, ticket_range: &TicketRange) -> ManagedVec<usize> {
let mut winning_ticket_ids = ManagedVec::new();
for ticket_id in ticket_range.first_id..=ticket_range.last_id {
let ticket_status = self.ticket_status(ticket_id).get();
if ticket_status == WINNING_TICKET {
winning_ticket_ids.push(ticket_id);
}

self.ticket_pos_to_id(ticket_id).clear();
}

winning_ticket_ids
}

#[view(getClaimTypeForUser)]
#[storage_mapper("claimedTokens")]
fn claim_list(&self) -> WhitelistMapper<Self::Api, ManagedAddress>;
fn claimed_tokens(&self, user: &ManagedAddress) -> SingleValueMapper<ClaimType>;
}
42 changes: 10 additions & 32 deletions launchpad-guaranteed-tickets-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
multiversx_sc::imports!();
multiversx_sc::derive_imports!();

use launchpad_common::{config::TokenAmountPair, launch_stage::Flags, tickets::WINNING_TICKET};
use launchpad_common::user_interactions::ClaimType;
use launchpad_common::{config::TokenAmountPair, launch_stage::Flags};

use crate::guaranteed_ticket_winners::GuaranteedTicketsSelectionOperation;

Expand Down Expand Up @@ -175,7 +176,8 @@ pub trait LaunchpadGuaranteedTickets:
fn claim_launchpad_tokens_endpoint(&self) {
self.require_not_paused();
let caller = self.blockchain().get_caller();
let user_results_processed = self.claim_list().contains(&caller);
let claim_type = self.claimed_tokens(&caller).get();
let user_results_processed = matches!(claim_type, ClaimType::All);
if !user_results_processed {
self.compute_launchpad_results(&caller);
};
Expand All @@ -197,36 +199,9 @@ pub trait LaunchpadGuaranteedTickets:
}

fn compute_launchpad_results(&self, caller: &ManagedAddress) {
self.require_claim_period();

let ticket_range = self.try_get_ticket_range(caller);
let nr_confirmed_tickets = self.nr_confirmed_tickets(caller).get();
let mut nr_redeemable_tickets = 0;

for ticket_id in ticket_range.first_id..=ticket_range.last_id {
let ticket_status = self.ticket_status(ticket_id).get();
if ticket_status == WINNING_TICKET {
self.ticket_status(ticket_id).clear();

nr_redeemable_tickets += 1;
}

self.ticket_pos_to_id(ticket_id).clear();
}

self.nr_confirmed_tickets(caller).clear();
self.ticket_range_for_address(caller).clear();
self.ticket_batch(ticket_range.first_id).clear();

if nr_redeemable_tickets > 0 {
self.nr_winning_tickets()
.update(|nr_winning_tickets| *nr_winning_tickets -= nr_redeemable_tickets);
}

self.claim_list().add(caller);

let nr_tickets_to_refund = nr_confirmed_tickets - nr_redeemable_tickets;
self.refund_ticket_payment(caller, nr_tickets_to_refund);
let nr_redeemable_tickets = self
.claim_refunded_tickets_and_launchpad_tokens(Self::empty_send_fn)
.nr_redeemable_tickets;

if nr_redeemable_tickets > 0 {
let tokens_per_winning_ticket = self.launchpad_tokens_per_winning_ticket().get();
Expand All @@ -238,6 +213,9 @@ pub trait LaunchpadGuaranteedTickets:
}
}

#[inline(always)]
fn empty_send_fn(&self, _address: &ManagedAddress, _payment: &EsdtTokenPayment) {}

#[only_owner]
#[endpoint(claimTicketPayment)]
fn claim_ticket_payment_endpoint(&self) {
Expand Down
2 changes: 1 addition & 1 deletion launchpad-guaranteed-tickets-v2/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ multiversx_sc_wasm_adapter::endpoints! {
getSupportAddress => support_address
isUserBlacklisted => is_user_blacklisted
confirmTickets => confirm_tickets
hasUserClaimedTokens => has_user_claimed
getClaimTypeForUser => claimed_tokens
setUnlockSchedule => set_unlock_schedule
getClaimableTokens => compute_claimable_tokens
getUserTotalClaimableBalance => user_total_claimable_balance
Expand Down
43 changes: 11 additions & 32 deletions launchpad-guaranteed-tickets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
multiversx_sc::imports!();
multiversx_sc::derive_imports!();

use launchpad_common::{config::TokenAmountPair, launch_stage::Flags, tickets::WINNING_TICKET};
use launchpad_common::{
config::TokenAmountPair, launch_stage::Flags, user_interactions::ClaimType,
};

use crate::guaranteed_ticket_winners::GuaranteedTicketsSelectionOperation;

Expand Down Expand Up @@ -157,7 +159,8 @@ pub trait LaunchpadGuaranteedTickets:
#[endpoint(claimLaunchpadTokens)]
fn claim_launchpad_tokens_endpoint(&self) {
let caller = self.blockchain().get_caller();
let user_results_processed = self.claim_list().contains(&caller);
let claim_type = self.claimed_tokens(&caller).get();
let user_results_processed = matches!(claim_type, ClaimType::All);
if !user_results_processed {
self.compute_launchpad_results(&caller);
};
Expand All @@ -173,36 +176,9 @@ pub trait LaunchpadGuaranteedTickets:
}

fn compute_launchpad_results(&self, caller: &ManagedAddress) {
self.require_claim_period();

let ticket_range = self.try_get_ticket_range(caller);
let nr_confirmed_tickets = self.nr_confirmed_tickets(caller).get();
let mut nr_redeemable_tickets = 0;

for ticket_id in ticket_range.first_id..=ticket_range.last_id {
let ticket_status = self.ticket_status(ticket_id).get();
if ticket_status == WINNING_TICKET {
self.ticket_status(ticket_id).clear();

nr_redeemable_tickets += 1;
}

self.ticket_pos_to_id(ticket_id).clear();
}

self.nr_confirmed_tickets(caller).clear();
self.ticket_range_for_address(caller).clear();
self.ticket_batch(ticket_range.first_id).clear();

if nr_redeemable_tickets > 0 {
self.nr_winning_tickets()
.update(|nr_winning_tickets| *nr_winning_tickets -= nr_redeemable_tickets);
}

self.claim_list().add(caller);

let nr_tickets_to_refund = nr_confirmed_tickets - nr_redeemable_tickets;
self.refund_ticket_payment(caller, nr_tickets_to_refund);
let nr_redeemable_tickets = self
.claim_refunded_tickets_and_launchpad_tokens(Self::empty_send_fn)
.nr_redeemable_tickets;

if nr_redeemable_tickets > 0 {
let tokens_per_winning_ticket = self.launchpad_tokens_per_winning_ticket().get();
Expand All @@ -214,6 +190,9 @@ pub trait LaunchpadGuaranteedTickets:
}
}

#[inline(always)]
fn empty_send_fn(&self, _address: &ManagedAddress, _payment: &EsdtTokenPayment) {}

#[only_owner]
#[endpoint(claimTicketPayment)]
fn claim_ticket_payment_endpoint(&self) {
Expand Down
Loading
Loading