Skip to content

Commit

Permalink
Merge pull request #58 from SundaeSwap-finance/pi/SSW-306-efficient-sqrt
Browse files Browse the repository at this point in the history
Resolve SSW-306
  • Loading branch information
Quantumplation authored Mar 5, 2024
2 parents db3d33e + 15f443c commit 12a55da
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
13 changes: 13 additions & 0 deletions lib/shared.ak
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ pub fn count_orders(tx_inputs: List<Input>) -> Int {
}
}

// Taken from unmerged PR: https://github.com/aiken-lang/stdlib/pull/73/files
pub fn is_sqrt(self: Int, x: Int) -> Bool {
x * x <= self && ( x + 1 ) * ( x + 1 ) > self
}

test is_sqrt1() {
is_sqrt(44203, 210)
}

test is_sqrt2() {
is_sqrt(975461057789971041, 987654321)
}

/// Check whether a specific value has *exactly* the right amount of tokens
/// This is important to, for example, efficiently check the pool output has the correct value
/// Check where this is used, because it's a very subtle bit of logic for where this is safe to do
Expand Down
10 changes: 6 additions & 4 deletions validators/pool.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use aiken/dict
use aiken/hash
use aiken/interval
use aiken/list
use aiken/math
use aiken/transaction.{
InlineDatum, Input, Mint, Output, OutputReference,
ScriptContext, Transaction, TransactionId,
Expand Down Expand Up @@ -387,11 +386,14 @@ validator(settings_policy_id: PolicyId) {
coin_a_amt
}

// Calculate the initial number of LP tokens; In particular, we adopt Uniswaps convention of
// computing this value as the square root of the product of the two values.
// Check that the quantity of LP tokens is correct; In particular, we adopt Uniswaps convention of
// using the sqrt of the product of the two values for the initial number of LP tokens to mint..
// This helps minimize precision loss: it gives decent initial liquidity values for a range of
// sizes of pools, such that an individual LP token is granular enough for depositing and withdrawing for most users.
expect Some(initial_lq) = math.sqrt(coin_a_amt_sans_protocol_fees * coin_b_amt)
// In particular, though, we don't calculate the sqrt here, which is an expensive function; we instead verify that the
// amount minted is valid by checking that it squares to the correct product
let initial_lq = pool_output_datum.circulating_lp
expect shared.is_sqrt(coin_a_amt_sans_protocol_fees * coin_b_amt, initial_lq)

// And check that we mint the correct tokens, and nothing else.
let expected_mint =
Expand Down

0 comments on commit 12a55da

Please sign in to comment.