andromedaprotocol/andromeda-core

[EPIC] Conditional Splitter Contract

Closed this issue · 6 comments

Description

Ability to add conditional thresholds via a conditional splitter contract allowing more specific use cases to be covered.

Implementation

Allow users to create conditional breakpoints in the splitter contract that alters the percentage after the breakpoints are met. For example someone may receive 10% split up until they receive 1000 of a particular token. After this point they would receive 5% instead.

Acceptance Criteria

  1. New contract created for Conditional Splitter.
  2. Contract implemented into webapp.
  3. Fully Tested

I had an interesting discussion with @daniel-wehbe concerning the contract's functionality which has led to this implementation:

What It Currently Does
The contract owner sets a list of thresholds and a list of recipients. Each recipient has a list of percentages each corresponding to a certain threshold.
The contract keeps track of all the funds that have been successfully distributed so far (including the refunds for the sender if there are any). This number is the basis of the thresholds.

Restrictions
The number of each recipient’s percentages should be equal to the amount of thresholds.
The index of the percentage corresponds to the index of the threshold. For example: the first percentage refers to the first threshold.
The sum of the recipients’ percentages never exceed 100 for any threshold.

Feedback is much appreciated.

@joemonem

I'm usually not a fan of indexed based correlations between data sets, we would need heavy validation to ensure nothing is mixed up. Would combining the percentages and thresholds be too complex of a data structure?

What do you think of linking the threshold to a percentage in a tuple. So this:

pub struct AddressPercentages {
    pub recipient: Recipient,
    pub percentages: Vec<Decimal>,
}

would become:

pub struct AddressPercentages {
    pub recipient: Recipient,
    pub percentages: Vec<(Threshold,Decimal)>,
}

and we ensure that each threshold is only used once for each recipient and that it exists here:

    pub thresholds: Vec<Threshold>,

Would nesting the AddressPercentages information in each Threshold be a viable option?

Just unsure about simple validation logic if we do the opposite.

Yeah I think it's viable, in that case we'll remove AddressPercentages and use the splitter's

pub struct AddressPercent {
    pub recipient: Recipient,
    pub percent: Decimal,
}

and change Threshold to

pub struct Threshold {
    pub min: Uint128,
    pub address_percent: Vec<AddressPercent>,
}

The contract is keeping track of the funds it has distributed using this:

pub const FUNDS_DISTRIBUTED: Item<Uint128> = Item::new("funds_distributed");

Would it be better to just include that figure in this struct:

pub struct ConditionalSplitter {
    /// The vector of thresholds which assign a percentage for a certain range of received funds
    pub thresholds: Vec<Threshold>,
    /// The lock's expiration time
    pub lock: MillisecondsExpiration,
}

which is being saved like this:

pub const CONDITIONAL_SPLITTER: Item<ConditionalSplitter> = Item::new("conditional_splitter");