Skip to content

Commit

Permalink
Handle Commission (#38)
Browse files Browse the repository at this point in the history
* update logic sellers

* add seller commission

* update order commission

* fix maximum encounter phase range
  • Loading branch information
ljttl3q04t authored Jun 24, 2024
1 parent c2bba19 commit 7682e62
Show file tree
Hide file tree
Showing 15 changed files with 216 additions and 127 deletions.
61 changes: 38 additions & 23 deletions lib/lb_v2/manager_validation.ak
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use aiken/list
use aiken/transaction.{InlineDatum, Input, Output, ValidityRange}
use aiken/transaction.{InlineDatum, Input, NoDatum, Output, ValidityRange}
use aiken/transaction/credential.{Address, ScriptCredential}
use aiken/transaction/value.{PolicyId, Value}
use lb_v2/types.{
AddSellers, Asset, CollectSellers, ManagerDatum, ManagerRedeemer, SellerDatum,
TreasuryDatum,
}
use lb_v2/utils.{
assert, minimum_seller_collected, must_get_start_end_validity, seller_auth_an,
assert, collect_seller_commission, minimum_seller_collected,
must_get_start_end_validity, seller_auth_an,
}
use lb_v2/validation.{build_default_seller_output}
use lb_v2/validation.{validate_seller_outputs}

// Assertions:
// - Manager, Treasury share the same LBE ID
Expand Down Expand Up @@ -80,32 +81,31 @@ pub fn validate_manage_seller(
}
when redeemer is {
AddSellers -> {
// Validate Add Sellers
let default_seller_output =
build_default_seller_output(
factory_policy_id: factory_policy_id,
base_asset: base_asset,
raise_asset: raise_asset,
seller_hash: seller_hash,
)
// Paying Seller Outputs correctly!
let seller_outputs =
list.filter(outputs, fn(output) { output == default_seller_output })
let seller_output_length = list.length(seller_outputs)
let mint_seller_count =
value.quantity_of(mint_value, factory_policy_id, seller_auth_an)
and {
end_valid_time_range < end_time,
is_cancelled == False,
// Mint should be correctly!
mint_value == value.from_asset(
factory_policy_id,
seller_auth_an,
seller_output_length,
mint_seller_count,
),
// Paying Manager Output correctly!
manager_out_datum == ManagerDatum {
..manager_in_datum,
seller_count: seller_count + seller_output_length,
seller_count: seller_count + mint_seller_count,
},
// Seller Outputs must pay correctly!
validate_seller_outputs(
outputs: outputs,
factory_policy_id: factory_policy_id,
base_asset: base_asset,
raise_asset: raise_asset,
seller_hash: seller_hash,
seller_count: mint_seller_count,
),
}
}
CollectSellers -> {
Expand All @@ -120,6 +120,7 @@ pub fn validate_manage_seller(
let (total_reserve_raise, total_penalty_input) =
apply_collect_sellers(
seller_inputs: seller_inputs,
outputs: outputs,
base_asset: base_asset,
raise_asset: raise_asset,
acc_raise: 0,
Expand Down Expand Up @@ -161,33 +162,47 @@ pub fn validate_manage_seller(

fn apply_collect_sellers(
seller_inputs: List<Input>,
outputs: List<Output>,
base_asset: Asset,
raise_asset: Asset,
acc_raise: Int,
acc_penalty: Int,
) -> (Int, Int) {
expect [input, ..inputs] = seller_inputs
expect Input { output: Output { datum: InlineDatum(raw_datum), .. }, .. } =
input
expect [seller_owner_output, ..remaining_outputs] = outputs
expect Input {
output: Output { datum: InlineDatum(raw_datum), value: in_value, .. },
..
} = input
expect seller_datum: SellerDatum = raw_datum
let SellerDatum {
base_asset: s_base_asset,
raise_asset: s_raise_asset,
amount,
penalty_amount,
owner,
..
} = seller_datum
expect assert(and {
s_base_asset == base_asset,
s_raise_asset == raise_asset,
}, @"Collect Sellers: invalid seller inputs' LBE ID")
expect and {
s_base_asset == base_asset,
s_raise_asset == raise_asset,
seller_owner_output == Output {
address: owner,
value: value.from_lovelace(
value.lovelace_of(in_value) - collect_seller_commission,
),
datum: NoDatum,
reference_script: None,
},
}
let collect_raise = acc_raise + amount
let collect_penalty = acc_penalty + penalty_amount
when inputs is {
[] -> (collect_raise, collect_penalty)
_ ->
apply_collect_sellers(
seller_inputs: inputs,
outputs: remaining_outputs,
base_asset: base_asset,
raise_asset: raise_asset,
acc_raise: collect_raise,
Expand Down
14 changes: 11 additions & 3 deletions lib/lb_v2/test_suits.ak
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use aiken/transaction/value.{PolicyId, Value, ada_asset_name, ada_policy_id}
use lb_v2/order_validation.{apply_collecting_orders}
use lb_v2/types.{Asset, FactoryDatum, OrderDatum, PenaltyConfig, UsingSeller}
use lb_v2/utils.{
calculate_penalty, fee_ada, make_wrapper_redeemer, order_auth_an,
calculate_penalty, make_wrapper_redeemer, order_auth_an, order_commission,
order_minimum_ada, sort_two_consecutive_factory_datum,
}
use lb_v2/validation.{build_default_collected_order_value}
Expand Down Expand Up @@ -212,7 +212,11 @@ test test_apply_collecting_orders_3() {
let order_out_datum = OrderDatum { ..dummy.order_datum, is_collected: True }
let order_out_value =
value.from_asset(dummy.factory_policy_id, order_auth_an, 1)
|> value.add(ada_policy_id, ada_asset_name, order_minimum_ada + fee_ada)
|> value.add(
ada_policy_id,
ada_asset_name,
order_minimum_ada + order_commission,
)
let order_out =
Output {
address: dummy.order_input.output.address,
Expand All @@ -239,7 +243,11 @@ test test_apply_collecting_orders_4() {
let order_out_datum = OrderDatum { ..dummy.order_datum, is_collected: True }
let order_out_value =
value.from_asset(dummy.factory_policy_id, order_auth_an, 1)
|> value.add(ada_policy_id, ada_asset_name, order_minimum_ada + fee_ada)
|> value.add(
ada_policy_id,
ada_asset_name,
order_minimum_ada + order_commission,
)
let order_out =
Output {
address: dummy.order_input.output.address,
Expand Down
5 changes: 3 additions & 2 deletions lib/lb_v2/treasury_validation.ak
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use lb_v2/types.{
use lb_v2/utils.{
amm_authen_policy_id, amm_factory_auth_asset_name, amm_pool_auth_asset_name,
create_pool_comission, default_burn_liquidity, max_base_fee_numerator,
max_penalty, min_base_fee_numerator, min_pool_allocation, treasury_auth_an,
treasury_minimum_ada, two_day_ms,
max_penalty, min_base_fee_numerator, min_pool_allocation, one_month_ms,
treasury_auth_an, treasury_minimum_ada, two_day_ms,
}

pub fn validate_creating_treasury_out(
Expand Down Expand Up @@ -82,6 +82,7 @@ pub fn validate_creating_treasury_out(
t_raise_asset == raise_asset,
start_time > end_valid_time_range,
start_time < end_time,
end_time - start_time <= one_month_ms,
// Make sure that datum with datum_hash has appeared on the blockchain, \
// later we can use methods such as db_sync, kupo to rebuild the datum.
when receiver_datum is {
Expand Down
4 changes: 3 additions & 1 deletion lib/lb_v2/types.ak
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ pub type ManagerRedeemer {
pub type SellerDatum {
// ValidatorHash of Factory Validator
factory_policy_id: PolicyId,
// Fee will be return to seller's owner (PubKey Address)
owner: Address,
// Asset aims to list
base_asset: Asset,
// Asset aims to raise
Expand All @@ -182,7 +184,7 @@ pub type OrderDatum {
// Asset aims to raise
raise_asset: Asset,
// Update order require owner authorize
// System will redeem | refund to owner address
// System will redeem | refund to owner address (should be Pubkey Address)
owner: Address,
// Amount of Raise Asset
amount: Int,
Expand Down
23 changes: 17 additions & 6 deletions lib/lb_v2/utils.ak
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pub const order_auth_an = #"6f72646572"
// The Asset Name of Manager Authen Token
pub const manager_auth_an = #"4d616e61676572"

// The default number of Sellers to set up when starting a new LBE
pub const default_number_seller = 20
// The minimum number of Sellers to set up when starting a new LBE
pub const minimum_number_seller = 10

pub const minimum_seller_collected = 20

Expand All @@ -37,12 +37,13 @@ pub const min_pool_allocation = 70
// The business requires a maximum penalty period of two final days.
pub const two_day_ms = 172800000

// 30 days in milliseconds = 30 * 24 * 60 * 60 * 1000
// The business requires a maximum encounter phase period is 30 days
pub const one_month_ms = 2592000000

// Maximum penalty rate based on business
pub const max_penalty = 25

// The ADA amount to reward the Operator
pub const fee_ada = 1_000_000

// the ADA amount store in Treasury UTxO
pub const treasury_minimum_ada = 3_000_000

Expand All @@ -55,8 +56,18 @@ pub const seller_minimum_ada = 2_000_000
// the ADA amount store in Order UTxO
pub const order_minimum_ada = 2_000_000

// Commissions:
// The ADA amount to reward the pool creator
pub const create_pool_comission = 8_000_000
pub const create_pool_comission = 10_000_000

// The ADA amount to reward the seller's colector
pub const collect_seller_commission = 250_000

// The ADA amount to reward the Operator
pub const order_commission = 250_000

// The ADA amount to reward the seller
pub const seller_commission = 1_500_000

// The AMM configs based on https://github.com/minswap/minswap-dex-v2
// The Asset Name of AMM Factory Authen Token
Expand Down
92 changes: 70 additions & 22 deletions lib/lb_v2/validation.ak
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ use lb_v2/types.{
}
use lb_v2/utils.{
amm_authen_policy_id, amm_pool_auth_asset_name, amm_pool_validation_hash,
assert, calculate_penalty, fee_ada, manager_auth_an, manager_minimum_ada,
must_get_start_end_validity, order_auth_an, order_minimum_ada, seller_auth_an,
seller_minimum_ada, treasury_auth_an,
assert, calculate_penalty, manager_auth_an, manager_minimum_ada,
must_get_start_end_validity, order_auth_an, order_commission,
order_minimum_ada, seller_auth_an, seller_commission, seller_minimum_ada,
treasury_auth_an,
}

fn is_equal_data(a: Data, b: Data) -> Bool {
Expand Down Expand Up @@ -539,6 +540,12 @@ pub fn validate_using_seller(
)
let order_input_count = list.length(order_inputs)
let order_output_count = list.length(order_outputs)
let new_order_count =
if order_output_count > order_input_count {
order_output_count - order_input_count
} else {
0
}
and {
// prevent spam
order_input_count + order_output_count > 0,
Expand All @@ -558,7 +565,12 @@ pub fn validate_using_seller(
},
) == [seller_input],
// Validate Seller Output
seller_output_value == seller_input_value,
seller_output_value == value.add(
seller_input_value,
ada_policy_id,
ada_asset_name,
seller_commission * new_order_count,
),
seller_output_rs == None,
seller_output_datum == SellerDatum {
..seller_in_datum,
Expand Down Expand Up @@ -654,7 +666,7 @@ pub fn apply_order(
|> value.add(
ada_policy_id,
ada_asset_name,
order_minimum_ada + fee_ada * 2,
order_minimum_ada + order_commission * 2,
)
let minimum_amount =
when minimum_order_raise is {
Expand Down Expand Up @@ -700,40 +712,76 @@ pub fn apply_order(
)
}

// return Seller Output when creating Treasury
pub fn build_default_seller_output(
pub fn validate_seller_outputs(
outputs: List<Output>,
factory_policy_id: ValidatorHash,
base_asset: Asset,
raise_asset: Asset,
seller_hash: ValidatorHash,
) -> Output {
let seller_address = credential.from_script(seller_hash)
// build default seller datum
let seller_datum =
SellerDatum {
seller_count: Int,
) -> Bool {
expect Some(seller_output) =
list.find(
outputs,
fn(output) {
let Output { address: Address { payment_credential, .. }, .. } = output
payment_credential == ScriptCredential(seller_hash)
},
)
expect Output {
datum: InlineDatum(raw_datum),
value: seller_value,
reference_script: None,
..
} = seller_output
expect datum: SellerDatum = raw_datum
let SellerDatum { owner, .. } = datum
expect
datum == SellerDatum {
factory_policy_id,
base_asset,
raise_asset,
amount: 0,
penalty_amount: 0,
owner,
}
// build default seller value
let seller_value =
value.from_lovelace(seller_minimum_ada)
|> value.add(factory_policy_id, seller_auth_an, 1)
Output {
address: seller_address,
value: seller_value,
datum: InlineDatum(seller_datum),
reference_script: None,
// all sellers have the same owner
and {
value.flatten(seller_value) == [
(ada_policy_id, ada_asset_name, seller_minimum_ada),
(factory_policy_id, seller_auth_an, 1),
],
datum == SellerDatum {
factory_policy_id,
base_asset,
raise_asset,
amount: 0,
penalty_amount: 0,
owner,
},
seller_count == list.foldl(
outputs,
0,
fn(output, cnt) {
if output == seller_output {
cnt + 1
} else {
cnt
}
},
),
}
}

pub fn build_default_collected_order_value(
factory_policy_id: ValidatorHash,
) -> Value {
value.from_asset(factory_policy_id, order_auth_an, 1)
|> value.add(ada_policy_id, ada_asset_name, order_minimum_ada + fee_ada)
|> value.add(
ada_policy_id,
ada_asset_name,
order_minimum_ada + order_commission,
)
}

// Check if the owner authorizes the transaction
Expand Down
24 changes: 14 additions & 10 deletions plutus.json

Large diffs are not rendered by default.

Loading

0 comments on commit 7682e62

Please sign in to comment.