Skip to content

Commit

Permalink
Merge branch 'master' into refactor-get-delta-y
Browse files Browse the repository at this point in the history
  • Loading branch information
zielvna committed Apr 4, 2024
2 parents b9fb040 + 6617027 commit 2390f2c
Show file tree
Hide file tree
Showing 4 changed files with 401 additions and 49 deletions.
6 changes: 3 additions & 3 deletions contracts/math/clamm.ral
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ Contract CLAMM(uints: Uints) extends Log() {
let mut result = U512 { lower: 0, higher: 0 }

if (roundingUp) {
result = uints.bigMulUp(deltaSqrtPrice, liquidity, one(LiquidityScale))
result = uints.bigAdd512(result, almostOne(SqrtPriceScale))
result = uints.bigMulDiv256(deltaSqrtPrice, liquidity, one(LiquidityScale))
result = uints.bigAdd512(result, uints.toU512(almostOne(SqrtPriceScale)))
result = uints.bigDiv(result, one(SqrtPriceScale), 1)
return uints.toU256(result)
} else {
result = uints.bigMulUp(deltaSqrtPrice, liquidity, one(LiquidityScale))
result = uints.bigMulDiv256(deltaSqrtPrice, liquidity, one(LiquidityScale))
result = uints.bigDiv(result, one(SqrtPriceScale), 1)
return uints.toU256(result)
}
Expand Down
74 changes: 63 additions & 11 deletions contracts/math/uints.ral
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct Result {
mut value: U512,
mut error: Bool
}

struct U512 {
mut higher: U256,
mut lower: U256
Expand All @@ -23,7 +28,7 @@ Contract Uints () {
return v.lower
}

pub fn bigAdd(a: U256, b: U256) -> U512 {
pub fn bigAdd256(a: U256, b: U256) -> U512 {
if (MaxU256 - a < b) {
return U512 {
higher: 1,
Expand Down Expand Up @@ -79,13 +84,60 @@ Contract Uints () {
return div(a, b, bDenominator, true)
}

pub fn bigAdd512(a: U512, b: U256) -> U512 {
let (aLowerB, overflow) = overflowingAdd(a.lower, b)
let aHigherOverflow = wrappingAdd(a.higher, overflow)
pub fn bigAdd512(a: U512, b: U512) -> U512 {
let (aLowerB, overflow) = overflowingAdd(a.lower, b.lower)
let aHigherOverflow = wrappingAdd(wrappingAdd(a.higher, b.higher), overflow)
return U512 { lower: aLowerB, higher: aHigherOverflow }
}

pub fn mul(a: U256, b: U256) -> U512 {
pub fn bigDivWrapper(a: U512, b: U256, bDenominator: U256, up: Bool) -> U512 {
assert!(b > 0, ArithmeticErrors.NotPositiveDivisor)

if (b == 1) {
return a
}

// Calculate new higher
let newHigher = a.higher * bDenominator
let higher = newHigher / b
let higherRemainder = newHigher % b
// calculate higher remainder
let maxDiv = MaxU256 / b
let deltaHigherRemainder = higherRemainder * maxDiv
// Calculate lower
let newLower = a.lower * bDenominator
let lower = newLower / b
let mut deltaLower = deltaHigherRemainder + lower

if (up) {
let lowerRemainder = newLower % b

let higherDecimal = deltaHigherRemainder % b
if (higherDecimal + lowerRemainder != 0) {
deltaLower = deltaLower + 1
}
}

return U512 {
higher: higher,
lower: deltaLower
}
}

pub fn bigDiv512(a: U512, b: U256, bDenominator: U256) -> U512 {
return bigDivWrapper(a, b, bDenominator, false)
}

pub fn bigDivUp512(a: U512, b: U256, bDenominator: U256) -> U512 {
return bigDivWrapper(a, b, bDenominator, true)
}

pub fn bigMul512(a: U512, b: U256) -> U512 {
let result = bigMul256(a.lower, b)
return bigAdd512(result, U512 { higher: a.higher * b, lower: 0 })
}

pub fn bigMul256(a: U256, b: U256) -> U512 {
let aLower = low128(a)
let aHigher = high128(a)
let bLower = low128(b)
Expand All @@ -106,18 +158,18 @@ Contract Uints () {
return U512 { higher: higher, lower: lower }
}

pub fn bigMul(a: U256, b: U256, bDenominator: U256) -> U512 {
let mut result = mul(a, b)
pub fn bigMulDiv256(a: U256, b: U256, bDenominator: U256) -> U512 {
let mut result = bigMul256(a, b)

result = bigDiv(result, bDenominator, 1)
result = bigDiv512(result, bDenominator, 1)

return result
}

pub fn bigMulUp(a: U256, b: U256, bDenominator: U256) -> U512 {
let mut result = mul(a, b)
pub fn bigMulDivUp256(a: U256, b: U256, bDenominator: U256) -> U512 {
let mut result = bigMul256(a, b)

result = bigAdd512(result, bDenominator - 1)
result = bigAdd512(result, toU512(bDenominator - 1))
result = bigDiv(result, bDenominator, 1)

return result
Expand Down
240 changes: 240 additions & 0 deletions test/clamm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,244 @@ describe('math tests', () => {
}
}
})

describe('calculate fee growth inside', () => {
let clamm: CLAMMInstance
const globalFeeGrowthX = 15_0000000000000000000000000000n
const globalFeeGrowthY = 15_0000000000000000000000000000n

const tickLowerIndex = -2n
const tickLowerFeeGrowthOutsideX = 0n
const tickLowerFeeGrowthOutsideY = 0n

const tickUpperIndex = 2n
const tickUpperFeeGrowthOutsideX = 0n
const tickUpperFeeGrowthOutsideY = 0n

beforeEach(async () => {
clamm = (await deployCLAMM(sender)).contractInstance
})

test('sqrt price between ticks', async () => {
// <────────────── ──────────────>
// fee_outside_t0| fee_growth_inside |fee_outside_t1
//<───────────── t0 ────── C ────── t1 ───────────────────>
// fee_growth_inside = fee_growth_global - t0.fee_outside - t1.fee_outside

const tickCurrent = 0n

// current tick inside range
// lower current upper
// | | |
// -2 0 2

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(15_0000000000000000000000000000n)
expect(result.returns[1]).toBe(15_0000000000000000000000000000n)
})

test('sqrt price below ticks', async () => {
// ───────fee_outside_t0──────────>
// |fee_growth_inside| fee_outside_t1
// ─────── c ─────── t0 ──────────────> t1 ───────────>
// fee_growth_inside = t0.fee_outside - t1.fee_outside

const tickCurrent = -4n

// current tick below range
// current lower upper
// | | |
// -4 2 2

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(0n)
expect(result.returns[1]).toBe(0n)
})

test('sqrt price above ticks', async () => {
// <──────────fee_outside_t0──────────
// fee_outside_t1 | fee_growth_inside|
// ────────────── t1 ──────────────── t0 ─────── c ───────────>
// fee_growth_inside = t0.fee_outside - t1.fee_outside

const tickCurrent = 3n

// current tick upper range
// lower upper current
// | | |
// -2 2 4

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(0n)
expect(result.returns[1]).toBe(0n)
})

test('sqrt price above ticks, liquidity outside upper tick', async () => {
const tickCurrent = 3n

const tickUpperFeeGrowthOutsideX = 1n
const tickUpperFeeGrowthOutsideY = 2n

const globalFeeGrowthX = 5_0000000000000000000000000000n
const globalFeeGrowthY = 5_0000000000000000000000000000n

// current tick upper range
// lower upper current
// | | |
// -2 2 3

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(1n)
expect(result.returns[1]).toBe(2n)
})

test('sqrt price in between ticks, liquidity outside upper tick', async () => {
const tickCurrent = 0n

const tickUpperFeeGrowthOutsideX = 2_0000000000000000000000000000n
const tickUpperFeeGrowthOutsideY = 3_0000000000000000000000000000n

// current tick inside range
// lower current upper
// | | |
// -2 0 2

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(13_0000000000000000000000000000n)
expect(result.returns[1]).toBe(12_0000000000000000000000000000n)
})

test('sqrt price in between ticks, liquidity outside lower tick', async () => {
const tickCurrent = 0n

const tickLowerFeeGrowthOutsideX = 2_0000000000000000000000000000n
const tickLowerFeeGrowthOutsideY = 3_0000000000000000000000000000n

// current tick inside range
// lower current upper
// | | |
// -2 0 2

const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(13_0000000000000000000000000000n)
expect(result.returns[1]).toBe(12_0000000000000000000000000000n)
})
})

describe('calculate fee growth inside - domain', () => {
let clamm: CLAMMInstance

const tickCurrent = 0n
const globalFeeGrowthX = 20_0000000000000000000000000000n
const globalFeeGrowthY = 20_0000000000000000000000000000n

const tickLowerIndex = -20n
const tickLowerFeeGrowthOutsideX = 20_0000000000000000000000000000n
const tickLowerFeeGrowthOutsideY = 20_0000000000000000000000000000n

const tickUpperIndex = -10n
const tickUpperFeeGrowthOutsideX = 15_0000000000000000000000000000n
const tickUpperFeeGrowthOutsideY = 15_0000000000000000000000000000n

beforeEach(async () => {
clamm = (await deployCLAMM(sender)).contractInstance
})

test('max fee growth', async () => {
const result = await clamm.methods.calculateFeeGrowthInside({
args: {
tickLowerIndex,
tickLowerFeeGrowthOutsideX,
tickLowerFeeGrowthOutsideY,
tickUpperIndex,
tickUpperFeeGrowthOutsideX,
tickUpperFeeGrowthOutsideY,
tickCurrent,
globalFeeGrowthX,
globalFeeGrowthY
}
})

expect(result.returns[0]).toBe(2n ** 256n - 1n - 5_0000000000000000000000000000n + 1n)
expect(result.returns[1]).toBe(2n ** 256n - 1n - 5_0000000000000000000000000000n + 1n)
})
})
})
Loading

0 comments on commit 2390f2c

Please sign in to comment.