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

Pi/pool-manage-fix #81

Merged
merged 16 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
AIKEN=$1

aiken() {
/home/pi/proj/aiken/target/release/aiken $*
Quantumplation marked this conversation as resolved.
Show resolved Hide resolved
${AIKEN} $*
}

set -e
Expand Down
55 changes: 3 additions & 52 deletions lib/calculation/process.ak
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use aiken/bytearray
use aiken/cbor
use aiken/dict.{Dict}
use aiken/hash.{Blake2b_256, Hash}
use aiken/interval.{Finite, IntervalBound, NegativeInfinity}
use aiken/math
use aiken/time.{PosixTime}
use aiken/interval
use aiken/transaction.{
InlineDatum, Input, NoDatum, Output, OutputReference, TransactionId,
ValidityRange,
Expand All @@ -27,38 +25,11 @@ use sundae/multisig
use types/order.{Destination, Fixed, Order, OrderDatum, SignedStrategyExecution}
use types/pool.{PoolDatum}

pub fn calculate_fees(
fees: (Int, Int),
market_open: PosixTime,
fee_finalized: PosixTime,
valid_from: PosixTime,
) {
// So, if the transaction is guaranteed to run after fee_finalized, charge the final fee rate
if valid_from > fee_finalized {
fees.2nd
} else {
// Otherwise, calculate the duration of this decay period
let duration = fee_finalized - market_open
if duration == 0 {
// If it's zero (market_open == fee_finalized) then just use the final fee rate
fees.2nd
} else {
// Otherwise, calculate how much has elapsed since the market open
// then the full range of the fee rate
// then, starting from the opening fee rate, linearly increase (or decrease) the fees by that range
let elapsed = valid_from - market_open
let range = fees.2nd - fees.1st
fees.1st + elapsed * range / duration
}
}
}

/// Construct the initial pool state for processing a set of orders
pub fn pool_input_to_state(
pool_token_policy: PolicyId,
datum: PoolDatum,
input: Output,
valid_from: IntervalBound<PosixTime>,
continuation: fn(
PolicyId,
AssetName,
Expand All @@ -82,8 +53,6 @@ pub fn pool_input_to_state(
circulating_lp,
bid_fees_per_10_thousand,
ask_fees_per_10_thousand,
market_open,
fee_finalized,
..
} = datum
let (asset_a, asset_b) = assets
Expand All @@ -102,28 +71,10 @@ pub fn pool_input_to_state(
// Scoopers could in theory set a wide validity range to cause users to overpay, but this should be considered malicious activity and
// get the scooper removed from the list of valid scoopers / ignore scooper rewards
// TODO: we could solve this by enforcing a validity range, and checking the length is within 4 hours.
let valid_from =
when valid_from.bound_type is {
NegativeInfinity -> market_open
Finite(t) -> math.max(t, market_open)
_ -> fail
}
// Calculate the fees per 10k rate to use for this whole scoop
// We let the creator of the pool specify a fee rate that decays (or increases) between market_open and fee_finalized
let bid_fees =
calculate_fees(
bid_fees_per_10_thousand,
market_open,
fee_finalized,
valid_from,
)
let ask_fees =
calculate_fees(
ask_fees_per_10_thousand,
market_open,
fee_finalized,
valid_from,
)
let bid_fees = bid_fees_per_10_thousand
let ask_fees = ask_fees_per_10_thousand
// Then construct the pool state. We include the assets here, instead of just the reserves, so we can check the values of each order
// TODO: we could potentially save quite a bit by not passing around this object, and passing around a lot of parameters instead...
continuation(
Expand Down
8 changes: 3 additions & 5 deletions lib/shared.ak
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,9 @@ pub fn oracle_sft_name() {
"oracle"
}

pub fn fees_in_legal_range(fees: (Int, Int)) {
pub fn fees_in_legal_range(fees: Int) {
and {
fees.1st >= 0,
fees.2nd >= 0,
fees.1st <= 10000,
fees.2nd <= 10000,
fees >= 0,
fees <= 10000,
}
}
4 changes: 2 additions & 2 deletions lib/tests/examples/ex_pool.ak
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ fn mk_pool_datum() -> PoolDatum {
),
),
circulating_lp: 20229488080013,
bid_fees_per_10_thousand: (2000, 500),
ask_fees_per_10_thousand: (2000, 500),
bid_fees_per_10_thousand: 2000,
ask_fees_per_10_thousand: 2000,
fee_manager: None,
market_open: 100,
fee_finalized: 1000,
Expand Down
4 changes: 2 additions & 2 deletions lib/types/pool.ak
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pub type PoolDatum {
/// The two values represent the fees as of `market_open` and as of `fee_finalized`, respectively, with a linear
/// decay from one to the other.
/// The transaction uses the valid_from field to charge the largest fee the transaction *could* be obligated to pay
bid_fees_per_10_thousand: (Int, Int),
ask_fees_per_10_thousand: (Int, Int),
bid_fees_per_10_thousand: Int,
ask_fees_per_10_thousand: Int,
// An optional multisig condition under which the protocol fees can be updated
fee_manager: Option<multisig.MultisigScript>,
/// The UNIX millisecond timestamp at which trading against the pool should be allowed
Expand Down
34 changes: 17 additions & 17 deletions plutus.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions validators/oracle.ak
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ fn mint_oracle(
identifier: pool_id,
assets: ((#"", #""), (rberry_policy_id, rberry_token_name)),
circulating_lp: 1_000_000_000,
bid_fees_per_10_thousand: (5, 5),
ask_fees_per_10_thousand: (5, 5),
bid_fees_per_10_thousand: 5,
ask_fees_per_10_thousand: 5,
fee_manager: None,
market_open: 0,
fee_finalized: 0,
Expand Down
1 change: 0 additions & 1 deletion validators/pool.ak
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ validator(
pool_script_hash,
datum,
pool_input,
validity_range.lower_bound,
)

// Process the orders in order, and decide the final pool state we should see
Expand Down
28 changes: 14 additions & 14 deletions validators/tests/pool.ak
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ type ScoopTestOptions {
edit_order_intended_destination: Option<Destination>,
edit_order_actual_destination: Option<Destination>,
edit_fee: Option<Value>,
edit_swap_fees: Option<((Int, Int), (Int, Int))>,
edit_new_swap_fees: Option<((Int, Int), (Int, Int))>,
edit_swap_fees: Option<(Int, Int)>,
edit_new_swap_fees: Option<(Int, Int)>,
edit_fee_admin: Option<Option<multisig.MultisigScript>>,
edit_withdrawals: Option<Dict<StakeCredential, Int>>,
edit_pool_input_address: Option<Address>,
Expand Down Expand Up @@ -206,7 +206,7 @@ test scoop_high_swap_fees() {
let options =
ScoopTestOptions {
..default_scoop_test_options(),
edit_swap_fees: Some(((swap_fee, swap_fee), (swap_fee, swap_fee))),
edit_swap_fees: Some((swap_fee, swap_fee)),
edit_order_1_out_value: Some(
value.from_lovelace(2_000_000)
|> value.add(
Expand Down Expand Up @@ -328,7 +328,7 @@ test scooper_not_in_settings() fail {
fn scoop(options: ScoopTestOptions) {
let user_addr = wallet_address(constants.payment_key)
let owner = multisig.Signature(constants.payment_key)
let fees = option.or_else(options.edit_swap_fees, ((5, 5), (5, 5)))
let fees = option.or_else(options.edit_swap_fees, (5, 5))
let pool_datum =
PoolDatum {
identifier: constants.pool_ident,
Expand Down Expand Up @@ -548,7 +548,7 @@ fn scoop(options: ScoopTestOptions) {
fn scoop_swap_deposit(options: ScoopTestOptions) {
let user_addr = wallet_address(constants.payment_key)
let owner = multisig.Signature(constants.payment_key)
let pool_fees = option.or_else(options.edit_swap_fees, ((5, 5), (5, 5)))
let pool_fees = option.or_else(options.edit_swap_fees, (5, 5))
let pool_datum =
PoolDatum {
identifier: constants.pool_ident,
Expand Down Expand Up @@ -777,7 +777,7 @@ fn withdraw_fees_transaction(options: ScoopTestOptions, withdraw_amount: Int, po
options.edit_pool_output_address,
default_pool_output_address,
)
let pool_fees = option.or_else(options.edit_swap_fees, ((5, 5), (5, 5)))
let pool_fees = option.or_else(options.edit_swap_fees, (5, 5))
let protocol_fees = 2_000_000
let pool_datum =
PoolDatum {
Expand Down Expand Up @@ -1019,7 +1019,7 @@ fn update_pool_fees_transaction(options: ScoopTestOptions) {
options.edit_pool_output_address,
default_pool_output_address,
)
let pool_fees = option.or_else(options.edit_swap_fees, ((5, 5), (5, 5)))
let pool_fees = option.or_else(options.edit_swap_fees, (5, 5))
let fee_manager =
option.or_else(
options.edit_fee_admin,
Expand Down Expand Up @@ -1063,7 +1063,7 @@ fn update_pool_fees_transaction(options: ScoopTestOptions) {
)

let new_pool_fees =
option.or_else(options.edit_new_swap_fees, ((10, 10), (310, 150)))
option.or_else(options.edit_new_swap_fees, (10, 10))
let pool_out_datum =
PoolDatum {
..pool_datum,
Expand Down Expand Up @@ -1132,7 +1132,7 @@ test illegal_new_pool_fees_test() fail {
let settings =
ScoopTestOptions {
..default_scoop_test_options(),
edit_new_swap_fees: Some(((10001, 10001), (10001, 10001))),
edit_new_swap_fees: Some((10001, 10001)),
}
update_pool_fees_transaction(settings)
}
Expand Down Expand Up @@ -1245,8 +1245,8 @@ fn mint_test_modify(
(constants.rberry_policy, constants.rberry_asset_name),
),
circulating_lp: 1_000_000_000,
bid_fees_per_10_thousand: (5, 5),
ask_fees_per_10_thousand: (5, 5),
bid_fees_per_10_thousand: 5,
ask_fees_per_10_thousand: 5,
fee_manager: None,
market_open: 0,
fee_finalized: 0,
Expand Down Expand Up @@ -1525,7 +1525,7 @@ fn evaporate_pool_tx(options: ScoopTestOptions, withdraw_amount: Int) {
let withdraw_fees_redeemer =
WithdrawFees { amount: withdraw_amount, treasury_output: 0, pool_input: 0 }
let pool_nft_name = shared.pool_nft_name(constants.pool_ident)
let pool_fees = option.or_else(options.edit_swap_fees, ((5, 5), (5, 5)))
let pool_fees = option.or_else(options.edit_swap_fees, (5, 5))
let pool_datum =
PoolDatum {
identifier: constants.pool_ident,
Expand Down Expand Up @@ -1612,7 +1612,7 @@ test attempt_evaporate_pool_test() {
let withdraw_fees_redeemer =
WithdrawFees { amount: 18_000_000, treasury_output: 0, pool_input: 0 }
let pool_nft_name = shared.pool_nft_name(constants.pool_ident)
let pool_fees = ((5, 5), (5, 5))
let pool_fees = (5, 5)
let pool_datum =
PoolDatum {
identifier: constants.pool_ident,
Expand Down Expand Up @@ -1683,7 +1683,7 @@ test attempt_evaporate_pool_test() {

test burn_pool() {
let user_addr = wallet_address(constants.payment_key)
let fees = ((5, 5), (5, 5))
let fees = (5, 5)
let pool_datum =
PoolDatum {
identifier: constants.pool_ident,
Expand Down
Loading