Skip to content

Commit

Permalink
Launchpad with custom unlock schedule
Browse files Browse the repository at this point in the history
  • Loading branch information
psorinionut committed Jun 10, 2024
1 parent a03e15a commit 3876b63
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 62 deletions.
107 changes: 46 additions & 61 deletions launchpad-guaranteed-tickets/src/token_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,19 @@ multiversx_sc::derive_imports!();
use launchpad_common::config;

pub const MAX_PERCENTAGE: u64 = 10_000;
pub const MAX_VESTING_RELEASES: usize = 50;

#[derive(TopEncode, TopDecode, TypeAbi)]
pub struct UnlockSchedule {
claim_start_round: u64,
initial_release_percentage: u64,
vesting_release_times: u64,
#[derive(TypeAbi, ManagedVecItem, TopEncode, TopDecode, NestedEncode, NestedDecode)]
pub struct VestingRelease {
vesting_release_epoch: u64,
vesting_release_percentage: u64,
vesting_release_period: u64,
}

impl UnlockSchedule {
pub fn new(
claim_start_round: u64,
initial_release_percentage: u64,
vesting_release_times: u64,
vesting_release_percentage: u64,
vesting_release_period: u64,
) -> Self {
UnlockSchedule {
claim_start_round,
initial_release_percentage,
vesting_release_times,
impl VestingRelease {
pub fn new(vesting_release_epoch: u64, vesting_release_percentage: u64) -> Self {
VestingRelease {
vesting_release_epoch,
vesting_release_percentage,
vesting_release_period,
}
}
}
Expand All @@ -36,14 +25,7 @@ impl UnlockSchedule {
pub trait TokenReleaseModule: config::ConfigModule {
#[only_owner]
#[endpoint(setUnlockSchedule)]
fn set_unlock_schedule(
&self,
claim_start_round: u64,
initial_release_percentage: u64,
vesting_release_times: u64,
vesting_release_percentage: u64,
vesting_release_period: u64,
) {
fn set_unlock_schedule(&self, vesting_releases: MultiValueEncoded<MultiValue2<u64, u64>>) {
let configuration = self.configuration();
require!(
!configuration.is_empty(),
Expand All @@ -52,43 +34,52 @@ pub trait TokenReleaseModule: config::ConfigModule {
let confirmation_period_start_block = configuration.get().confirmation_period_start_block;

let current_block = self.blockchain().get_block_nonce();
let current_round = self.blockchain().get_block_round();
require!(
current_block < confirmation_period_start_block || self.unlock_schedule().is_empty(),
"Can't change the unlock schedule"
);
require!(
claim_start_round >= current_round,
"Wrong claim start round"
);
require!(
vesting_release_period > 0 || initial_release_percentage == MAX_PERCENTAGE,
"Wrong vesting release recurrency"
!vesting_releases.is_empty() && vesting_releases.len() <= MAX_VESTING_RELEASES,
"Wrong release schedule"
);

let unlock_percentage =
initial_release_percentage + vesting_release_times * vesting_release_percentage;
let mut unlock_schedule = ManagedVec::new();
let mut total_unlock_percentage = 0;
let mut last_release_epoch = self.blockchain().get_block_epoch();

for vesting_release in vesting_releases {
let (vesting_release_epoch, vesting_release_percentage) = vesting_release.into_tuple();

require!(
vesting_release_epoch >= last_release_epoch,
"The release epochs must be in order"
);

total_unlock_percentage += vesting_release_percentage;
last_release_epoch = vesting_release_epoch;

unlock_schedule.push(VestingRelease::new(
vesting_release_epoch,
vesting_release_percentage,
));
}

require!(
unlock_percentage == MAX_PERCENTAGE,
total_unlock_percentage == MAX_PERCENTAGE,
"Unlock percentage is not 100%"
);

let unlock_schedule = UnlockSchedule::new(
claim_start_round,
initial_release_percentage,
vesting_release_times,
vesting_release_percentage,
vesting_release_period,
);

self.unlock_schedule().set(unlock_schedule);
}

#[view(getClaimableTokens)]
fn compute_claimable_tokens(&self, address: &ManagedAddress) -> BigUint {
let user_total_claimable_balance = self.user_total_claimable_balance(address).get();
let user_claimed_balance = self.user_claimed_balance(address).get();
require!(
user_total_claimable_balance > 0,
"User has no claimable tokens"
);
require!(
user_claimed_balance < user_total_claimable_balance,
"Already claimed all tokens"
Expand All @@ -99,24 +90,18 @@ pub trait TokenReleaseModule: config::ConfigModule {
return BigUint::zero();
}
let unlock_schedule = unlock_schedule_mapper.get();
let current_round = self.blockchain().get_block_round();
if unlock_schedule.claim_start_round > current_round {
return BigUint::zero();
}

if unlock_schedule.initial_release_percentage == MAX_PERCENTAGE {
return user_total_claimable_balance;
let current_epoch = self.blockchain().get_block_epoch();
let mut current_claimable_percentage = 0;
for vesting_release in unlock_schedule.iter() {
if vesting_release.vesting_release_epoch < current_epoch {
break;
}

current_claimable_percentage += vesting_release.vesting_release_percentage;
}

let rounds_passed = current_round - unlock_schedule.claim_start_round;
let mut claimable_periods = rounds_passed / unlock_schedule.vesting_release_period;
if claimable_periods > unlock_schedule.vesting_release_times {
claimable_periods = unlock_schedule.vesting_release_times;
}
let claimable_percentage = unlock_schedule.initial_release_percentage
+ unlock_schedule.vesting_release_percentage * claimable_periods;
let current_claimable_tokens =
&user_total_claimable_balance * claimable_percentage / MAX_PERCENTAGE;
&user_total_claimable_balance * current_claimable_percentage / MAX_PERCENTAGE;

current_claimable_tokens - user_claimed_balance
}
Expand All @@ -131,5 +116,5 @@ pub trait TokenReleaseModule: config::ConfigModule {

#[view(getUnlockSchedule)]
#[storage_mapper("unlockSchedule")]
fn unlock_schedule(&self) -> SingleValueMapper<UnlockSchedule>;
fn unlock_schedule(&self) -> SingleValueMapper<ManagedVec<VestingRelease>>;
}
2 changes: 1 addition & 1 deletion launchpad/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ multiversx_sc_wasm_adapter::endpoints! {
getLaunchpadTokensPerWinningTicket
getTicketPrice
getNumberOfWinningTickets
getTotalNumberOfWinningTickets
getTotalLaunchpadTokensDeposited
setTicketPrice
setLaunchpadTokensPerWinningTicket
setConfirmationPeriodStartBlock
Expand Down

0 comments on commit 3876b63

Please sign in to comment.