DiminishingAirdrop

Diminishing Airdrop


Create Diminishing Airdrop

Commands

[UTXO_SPENDER_1, UTXO_SPENDER_2, ... , UTXO_SPENDER_N] is a list of the UTXOs getting spent. POOL_AMOUNT is the total amount available to be airdropped. STEPDOWN_AMOUNT is the amount that the Airdrop diminishes by per step. STEPDOWN_PERIOD is the amount of claims before the airdrop diminishes. MAX_AIRDROP is the first airdrop amount that will be received at the beginning of the STEPDOWN_PERIOD. MIN_AIRDROP is the last airdrop amount that will be received at the end of the STEPDOWN_PERIOD. CHANGE_UTXO is the UTXO the change gets bound to. SINGLE DROP is true or false and indicates if multiple claims can be made from one address or not.

Single Diminishing Airdrop

<TXID,
    {CONTRACT_ID_1:DIMAIRDROP[
        [UTXO_SPENDER_1, UTXO_SPENDER_2, ... , UTXO_SPENDER_N],
        POOL_AMOUNT,
        STEPDOWN_AMOUNT,
        STEPDOWN_PERIOD,
        MAX_AIRDROP,
        MIN_AIRDROP,
        CHANGE_UTXO,
        SINGLE_DROP]}>

Batched Diminishing Airdrop

<TXID,
    {CONTRACT_ID_1:DIMAIRDROP[
        [UTXO_SPENDER_1, UTXO_SPENDER_2, ... , UTXO_SPENDER_N],
        POOL_AMOUNT,
        STEPDOWN_AMOUNT,
        STEPDOWN_PERIOD,
        MAX_AIRDROP,
        MIN_AIRDROP,
        CHANGE_UTXO]}>
    {CONTRACT_ID_2:DIMAIRDROP[
        [UTXO_SPENDER_1, UTXO_SPENDER_2, ... , UTXO_SPENDER_N],
        POOL_AMOUNT,
        STEPDOWN_AMOUNT,
        STEPDOWN_PERIOD,
        MAX_AIRDROP,
        MIN_AIRDROP,
        CHANGE_UTXO]},
    ...,
    {CONTRACT_ID_N:DIMAIRDROP[
        [UTXO_SPENDER_1, UTXO_SPENDER_2, ... , UTXO_SPENDER_N],
        POOL_AMOUNT,
        STEPDOWN_AMOUNT,
        STEPDOWN_PERIOD,
        MAX_AIRDROP,
        MIN_AIRDROP,
        CHANGE_UTXO]}>

Examples

Single Diminishing Airdrop

<8d8f887752e0e3b5fbfc04958a54c107211aa1cd19062cf73bc8e8436fbc0c74,
    {3b1b20518485ec89ce9acf5bb23c5ccdb0ac26d0661e377014e894d295eec29e:DIMAIRDROP[
        [8c6be55f904d5711b6a3edb7921981fcdbe4e9b67c98ac06e0c0b9b121dc070c:1],
        40000000000000,
        10,
        160,
        250,
        50,
        TXID:1,
        true]}>

Batched Diminishing Airdrop

[!NOTE] Coming soon!

Implementations

Rust

pub fn create_dim_airdrop(&mut self, txid: &String, payload: &String, sender_utxos: &Vec<String>, pool_amount: &u64, step_down_amount: &u64, step_period_amount: &u64, max_airdrop: &u64, min_airdrop: &u64, change_utxo: &String, single_drop: &bool, current_block_height: u64) -> Result<(String, u64, bool), String> {
    let mut owners_amount: u64 = 0;
    for sender_utxo in sender_utxos.clone() {
        if self.owners.contains_key(&sender_utxo) {
            owners_amount += self.owners[&sender_utxo];
        }
    }

    if owners_amount == 0 {
        return Err("create_dim_airdrop: owner amount is zero".to_string());
    }

    if pool_amount > &owners_amount {
        return Err("create_dim_airdrop: pool amount is more than the owned amount".to_string());
    }

    let mut drips = match self.drips.clone() {
        Some(drips) => drips,
        None => HashMap::new(),
    };

    let mut new_owner = (change_utxo.to_string(),0, false);
    let mut diminishing_airdrops = match self.diminishing_airdrops.clone() {
        Some(diminishing_airdrops) => diminishing_airdrops,
        None => HashMap::new(),
    };

    for sender_utxo in sender_utxos.clone() {
        if self.owners.contains_key(&sender_utxo.clone()) {
            self.owners.remove(&sender_utxo);
            if let Some(old_drips) = drips.get(&sender_utxo) {
                let mut new_drips: Vec<Drip> = Vec::new();
                for drip in old_drips {
                    let new_drip = Drip {
                        block_end: drip.block_end.clone(),
                        drip_amount: drip.drip_amount.clone(),
                        amount: drip.amount.clone() - (current_block_height - drip.start_block) * drip.drip_amount,
                        start_block: current_block_height,
                        last_block_dripped:current_block_height.clone()
                    };
                    new_drips.push(new_drip.clone());
                }

                drips.insert(change_utxo.clone(),new_drips);
                // Remove the old drip from the vector
                drips.remove(&sender_utxo);
                new_owner.2 = true;
            }
        }
    }

    let change_amt: u64 = owners_amount - pool_amount;
    if change_amt > 0 {
        if self.owners.contains_key(change_utxo) {
            let new_amount = self.owners[change_utxo] + change_amt;
            new_owner.1 = new_amount.clone();
            self.owners.insert(change_utxo.to_string(), new_amount);
        } else {
            new_owner.1 = change_amt.clone();
            self.owners.insert(change_utxo.to_string(), change_amt);
        }
    }

    let dim_airdrop = DimAirdrop {
        pool_amount: *pool_amount,
        step_down_amount: *step_down_amount,
        step_period_amount: *step_period_amount,
        max_airdrop: *max_airdrop,
        min_airdrop: *min_airdrop,
        current_airdrop: *max_airdrop,
        current_in_period: 0,
        amount_airdropped: 0,
        last_airdrop_split: None,
        claimers: HashMap::new(),
        single_drop: *single_drop,
    };

    diminishing_airdrops.insert(sender_utxos[0].clone(), dim_airdrop);

    self.payloads.insert(txid.to_string(), payload.to_string());
    self.diminishing_airdrops = Some(diminishing_airdrops);
    self.supply -= pool_amount;
    self.drips = Some(drips);
    return Ok(new_owner);
}

Claim Diminishing Airdrop

Commands

AIRDROP_ID is the first spender UTXO from the DIMAIRDROP call. RECIEVER_UTXO is the UTXO the claimant wishes to bind to.

<TXID,
    {CONTRACT_ID:CLAIM_DIMAIRDROP[
        AIRDROP_ID,
        RECIEVER_UTXO]}>

Examples

<55c9d410e1c0fa7ff62efbad05361da919f7c77b7ef14590e6db5d4a1954a698,
    {3b1b20518485ec89ce9acf5bb23c5ccdb0ac26d0661e377014e894d295eec29e:CLAIM_DIMAIRDROP[
        8c6be55f904d5711b6a3edb7921981fcdbe4e9b67c98ac06e0c0b9b121dc070c:1,
        TXID:0]}

Implementations

Rust

pub fn claim_dim_airdrop(&mut self, txid: &String, payload: &String, claim_id: &String, reciever_utxo: &String, pending: bool, donater_pub_address: &String) -> Result<(String, u64, bool), String> {
    let mut diminishing_airdrops = match self.diminishing_airdrops.clone() {
        Some(diminishing_airdrops) => diminishing_airdrops,
        None => return Err("claim_dim_airdrop: contract has reached no claimable diminishing airdrops".to_string()),
    };

    let mut dim_airdrop: DimAirdrop =  match diminishing_airdrops.get(claim_id) {
        Some(dim_airdrop) => dim_airdrop.clone(),
        None => return Err("claim_dim_airdrop: diminishing airdrop claim id not found".to_string()),
    };

    let mut new_owner = (reciever_utxo.to_string(), 0, false);
    if dim_airdrop.step_period_amount == dim_airdrop.current_in_period {
        dim_airdrop.current_in_period = 0;
        if dim_airdrop.current_airdrop > dim_airdrop.min_airdrop {
            dim_airdrop.current_airdrop -= dim_airdrop.step_down_amount; 
        }
    }

    let mut airdrop_amount = dim_airdrop.current_airdrop;
    if dim_airdrop.amount_airdropped + dim_airdrop.current_airdrop >= dim_airdrop.pool_amount {
        airdrop_amount = dim_airdrop.pool_amount  - dim_airdrop.amount_airdropped;
    }

    let drips = match self.drips.clone() {
        Some(drips) => drips,
        None => HashMap::new(),
    };

    let mut pending_claims = match self.pending_claims.clone() {
        Some(pending_claims) => pending_claims,
        None => HashMap::new(),
    };

    if pending {
        pending_claims.insert(reciever_utxo.to_string(), airdrop_amount);
        let mut new_amount = airdrop_amount;
        if self.owners.contains_key(reciever_utxo) {
            new_amount = self.owners[reciever_utxo] + airdrop_amount;
        }

        new_owner.1 = new_amount;
     } else {
        pending_claims.remove(reciever_utxo);
         if self.owners.contains_key(reciever_utxo) {
            let new_amount = self.owners[reciever_utxo] + airdrop_amount;
            new_owner.1 = new_amount.clone();
            self.owners.insert(reciever_utxo.to_string(), new_amount);
        } else {
            new_owner.1 = airdrop_amount;
            self.owners.insert(reciever_utxo.to_string(), airdrop_amount);
        }
     }

    if drips.contains_key(reciever_utxo) {
        new_owner.2 = true;
    }

    if dim_airdrop.single_drop {
        dim_airdrop.claimers.insert(donater_pub_address.to_string(), airdrop_amount);
    }

    dim_airdrop.amount_airdropped += airdrop_amount;
    dim_airdrop.current_in_period += 1;
    if dim_airdrop.amount_airdropped == dim_airdrop.pool_amount  {
        diminishing_airdrops.remove(claim_id);      
    }else{
        diminishing_airdrops.insert(claim_id.to_string(), dim_airdrop);
    }
    
    self.supply += airdrop_amount;
    self.diminishing_airdrops = Some(diminishing_airdrops);
    self.pending_claims = Some(pending_claims);
    self.payloads.insert(txid.to_string(), payload.to_string());
    return Ok(new_owner);
}