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

export Pool Direct Interaction Redeemer #61

Draft
wants to merge 1 commit into
base: pump-plutus-v3
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 lib/amm_dex_v2/pool_validation.ak
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ pub fn get_pool_creation_expected_mint(
}

// This function get Pool output from output list and make sure there's single Pool Output
fn get_single_pool_output(
pub fn get_single_pool_output(
all_outputs: List<Output>,
pool_payment_credential: PaymentCredential,
) -> Output {
Expand Down
26 changes: 26 additions & 0 deletions lib/amm_dex_v2/types.ak
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,35 @@ pub type UpdatePoolParametersAction {
UpdatePoolStakeCredential
}

pub type DirectPoolAction {
DirectSwap {
// The AToB direction of swap request. True for A -> B and False for B -> A
a_to_b_direction: Bool,
// Amount of Asset In which users want to exchange
swap_amount: Int,
// Minimum amount of Asset Out which users want to receive after exchanging
minimum_receive: Int,
}
DirectDeposit {
deposit_amount_a: Int,
deposit_amount_b: Int,
// The minimum amount of LP Token which users want to receive after depositing
minimum_lp: Int,
}
DirectWithdraw {
lp_amount: Int,
// minimum received amounts of Asset A
minimum_asset_a: Int,
// minimum received amounts of Asset B
minimum_asset_b: Int,
}
}

pub type PoolRedeemer {
Batching
UpdatePoolParameters { action: UpdatePoolParametersAction }
WithdrawFeeSharing
DirectInteract { action: DirectPoolAction, integrator_index: Int }
}

pub type PoolBatchingRedeemer {
Expand Down Expand Up @@ -335,6 +360,7 @@ pub type GlobalSetting {
pool_stake_key_updater: PoolAuthorizationMethod,
// The actor who can update the Pool's dynamic fee.
pool_dynamic_fee_updater: PoolAuthorizationMethod,
integrators: List<PoolAuthorizationMethod>,
// The actor who can update the addresses mentioned above.
// This admin can be transferred to another wallet and should be stored in the most secure location.
admin: PoolAuthorizationMethod,
Expand Down
6 changes: 6 additions & 0 deletions validators/authen_minting_policy.ak
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ fn validate_global_setting(global_setting: GlobalSetting) -> Bool {
fee_sharing_taker,
pool_stake_key_updater,
pool_dynamic_fee_updater,
integrators,
admin,
} = global_setting
and {
Expand All @@ -261,6 +262,11 @@ fn validate_global_setting(global_setting: GlobalSetting) -> Bool {
batchers,
fn(batcher) { validate_pool_authorization_method(batcher) },
),
!builtin.null_list(integrators),
list.all(
integrators,
fn(integrator) { validate_pool_authorization_method(integrator) },
),
}
}

Expand Down
189 changes: 186 additions & 3 deletions validators/pool_validator.ak
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use aiken/builtin
use aiken/collection/list
use aiken/collection/pairs
use aiken/primitive/bytearray
use amm_dex_v2/math
use amm_dex_v2/order_validation
use amm_dex_v2/pool_validation
use amm_dex_v2/types.{
Batching, BatchingPool, GlobalSetting, OrderDatum, PAMSignature,
PAMSpendScript, PAMWithdrawScript, PoolBatchingRedeemer, PoolDatum,
PoolRedeemer, SwapMultiRouting, SwapRouting, UpdateDynamicFee, UpdatePoolFee,
Batching, BatchingPool, DirectDeposit, DirectInteract, DirectSwap,
DirectWithdraw, GlobalSetting, OrderDatum, PAMSignature, PAMSpendScript,
PAMWithdrawScript, PoolBatchingRedeemer, PoolDatum, PoolRedeemer,
SwapMultiRouting, SwapRouting, UpdateDynamicFee, UpdatePoolFee,
UpdatePoolParameters, UpdatePoolStakeCredential, WithdrawFeeSharing,
}
use amm_dex_v2/utils
Expand Down Expand Up @@ -130,6 +132,187 @@ validator pool_validator(
),
}
}
DirectInteract(action, integrator_index) -> {
let Transaction {
inputs,
reference_inputs,
outputs,
mint,
withdrawals,
extra_signatories,
..
} = transaction
expect Some(pool_input) = transaction.find_input(inputs, pool_input_ref)
let Input {
output: Output { address: pool_in_address, value: pool_in_value, .. },
..
} = pool_input
let Address {
payment_credential: pool_in_address_payment_credential,
..
} = pool_in_address
let global_setting =
pool_validation.get_and_validate_global_setting(
reference_inputs: reference_inputs,
authen_policy_id: authen_policy_id,
)
let GlobalSetting { integrators, .. } = global_setting
let integrator = utils.list_at_index(integrators, integrator_index)
expect and {
// Transaction must be executed by the correct authorizer
utils.authorize_pool_license(
author: integrator,
transaction_inputs: inputs,
withdrawals: withdrawals,
extra_signatories: extra_signatories,
),
// Verify that the transaction spends only one Single Pool Script and does not contain any other scripts in its inputs, except for the Author, in cases where the Author is a script
pool_validation.has_only_pool_and_author(
inputs: inputs,
pool_address: pool_in_address,
pool_author: integrator,
),
// This Redeemer won't mint anything
assets.is_zero(mint),
}
let Output {
address: pool_out_address,
value: pool_out_value,
datum: raw_pool_out_datum,
..
} =
pool_validation.get_single_pool_output(
all_outputs: outputs,
pool_payment_credential: pool_in_address_payment_credential,
)

expect and {
// Pool Input contains 1 valid Pool NFT Token
assets.quantity_of(
pool_in_value,
authen_policy_id,
utils.pool_auth_asset_name,
) == 1,
// Pool Output contains 1 valid Pool NFT Token
assets.quantity_of(
pool_out_value,
authen_policy_id,
utils.pool_auth_asset_name,
) == 1,
}
expect pool_out_datum: PoolDatum =
utils.must_find_script_inline_datum(raw_pool_out_datum)
let PoolDatum {
pool_batching_stake_credential: pool_in_stake_credential,
asset_a: pool_in_asset_a,
asset_b: pool_in_asset_b,
total_liquidity: pool_in_total_liquidity,
reserve_a: pool_in_reserve_a,
reserve_b: pool_in_reserve_b,
base_fee_a_numerator: pool_in_base_fee_a_numerator,
base_fee_b_numerator: pool_in_base_fee_b_numerator,
fee_sharing_numerator_opt: pool_in_fee_sharing_numerator_opt,
allow_dynamic_fee: pool_in_allow_dynamic_fee,
} = datum
let PoolDatum {
pool_batching_stake_credential: pool_out_stake_credential,
asset_a: pool_out_asset_a,
asset_b: pool_out_asset_b,
total_liquidity: pool_out_total_liquidity,
reserve_a: pool_out_reserve_a,
reserve_b: pool_out_reserve_b,
base_fee_a_numerator: pool_out_base_fee_a_numerator,
base_fee_b_numerator: pool_out_base_fee_b_numerator,
fee_sharing_numerator_opt: pool_out_fee_sharing_numerator_opt,
allow_dynamic_fee: pool_out_allow_dynamic_fee,
} = pool_out_datum
expect and {
// Irrelevant fields on Pool Datum must be unchanged
pool_in_stake_credential == pool_out_stake_credential,
pool_in_asset_a == pool_out_asset_a,
pool_in_asset_b == pool_out_asset_b,
pool_in_base_fee_a_numerator == pool_out_base_fee_a_numerator,
pool_in_base_fee_b_numerator == pool_out_base_fee_b_numerator,
pool_in_fee_sharing_numerator_opt == pool_out_fee_sharing_numerator_opt,
pool_in_allow_dynamic_fee == pool_out_allow_dynamic_fee,
// Pool Address must be unchanged (both Payment and Stake Credential)
pool_in_address == pool_out_address,
}
when action is {
DirectSwap(a_to_b, swap_amount, min_receive) -> {
expect swap_amount > 0
expect min_receive > 0
expect pool_in_total_liquidity == pool_out_total_liquidity
let (reserve_in, reserve_out, trading_fee_numerator) =
if a_to_b {
(
pool_in_reserve_a,
pool_in_reserve_b,
pool_in_base_fee_a_numerator,
)
} else {
(
pool_in_reserve_b,
pool_in_reserve_a,
pool_in_base_fee_b_numerator,
)
}
let amount_out =
math.calculate_amount_out(
reserve_in: reserve_in,
reserve_out: reserve_out,
amount_in: swap_amount,
trading_fee_numerator: trading_fee_numerator,
)
let earned_fee_in =
math.calculate_earned_fee_in(
amount_in: swap_amount,
trading_fee_numerator: trading_fee_numerator,
fee_sharing_numerator_opt: pool_in_fee_sharing_numerator_opt,
)
expect amount_out >= min_receive
if a_to_b {
and {
pool_in_reserve_a + swap_amount - earned_fee_in == pool_out_reserve_a,
pool_in_reserve_b - amount_out == pool_out_reserve_b,
(
pool_in_value
|> assets.add(
pool_in_asset_a.policy_id,
pool_in_asset_a.asset_name,
swap_amount,
)
|> assets.add(
pool_in_asset_b.policy_id,
pool_in_asset_b.asset_name,
-amount_out,
)
) == pool_out_value,
}
} else {
and {
pool_in_reserve_b + swap_amount - earned_fee_in == pool_out_reserve_b,
pool_in_reserve_a - amount_out == pool_out_reserve_a,
(
pool_in_value
|> assets.add(
pool_in_asset_a.policy_id,
pool_in_asset_a.asset_name,
-amount_out,
)
|> assets.add(
pool_in_asset_b.policy_id,
pool_in_asset_b.asset_name,
swap_amount,
)
) == pool_out_value,
}
}
}
DirectDeposit(_, _, _) -> todo
DirectWithdraw(_, _, _) -> todo
}
}
}
}

Expand Down
Loading