Skip to content

Commit

Permalink
Merge pull request #44 from invariant-labs/refactor-calculate-fee-gro…
Browse files Browse the repository at this point in the history
…wth-inside

Refactor calculate fee growth inside
  • Loading branch information
Sniezka1927 authored Apr 4, 2024
2 parents 22bff5c + 30a2305 commit 9e084e8
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 0 deletions.
5 changes: 5 additions & 0 deletions contracts/math/uints.ral
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ Contract Uints () {
return U512 { lower: aLowerBLower, higher: aHigherBHigherOverflow }
}

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

pub fn mul(a: U256, b: U256) -> U512 {
let aLower = low128(a)
let aHigher = high128(a)
Expand Down
241 changes: 241 additions & 0 deletions test/clamm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ONE_ALPH, web3 } from '@alephium/web3'
import { getSigner } from '@alephium/web3-test'
import { PrivateKeyWallet } from '@alephium/web3-wallet'
import { assert } from 'console'
import { CLAMMInstance } from '../artifacts/ts'
import { deployCLAMM } from '../src/utils'

web3.setCurrentNodeProvider('http://127.0.0.1:22973')
Expand Down Expand Up @@ -348,4 +349,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)
})
})
})
55 changes: 55 additions & 0 deletions test/uints.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,61 @@ describe('uints tests', () => {
}
})

test('big mul 512', async () => {
const uints = await deployUints(sender)
{
const a = { higher: 0n, lower: 123n }
const b = 2n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 246n })
// expected: 246
// real: 246
}
{
const a = { higher: 0n, lower: 340282366920938463463374607431768211457n }
const b = 340282366920938463463374607431768211457n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({ higher: 1n, lower: 680564733841876926926749214863536422913n })
// expected: 115792089237316195423570985008687907853950549399482440966384333222776666062849
// real: 115792089237316195423570985008687907853950549399482440966384333222776666062849
}
{
const a = { higher: 0n, lower: 115792089237316195423570985008687907853269984665640564039457584007913129639935n }
const b = 115792089237316195423570985008687907853269984665640564039457584007913129639935n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({
higher: 115792089237316195423570985008687907853269984665640564039457584007913129639934n,
lower: 1n
})
// expected: 13407807929942597099574024998205846127479365820592393377723561443721764030073315392623399665776056285720014482370779510884422601683867654778417822746804225
// real: 13407807929942597099574024998205846127479365820592393377723561443721764030073315392623399665776056285720014482370779510884422601683867654778417822746804225
}
{
const a = { higher: 0n, lower: 500n }
const b = 0n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({ higher: 0n, lower: 0n })
}
{
const a = { higher: 1n, lower: 115792089237316195423570985008687907853269984665640564039457584007913129639935n }
const b = 100n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({
higher: 199n,
lower: 115792089237316195423570985008687907853269984665640564039457584007913129639836n
})
}
{
const a = { higher: 340282366920938463463374607431768211455n, lower: 340282366920938463463374607431768211455n }
const b = 340282366920938463463374607431768211455n
const result = (await uints.contractInstance.methods.mul512({ args: { a, b } })).returns
expect(result).toStrictEqual({
higher: 115792089237316195423570985008687907852589419931798687112530834793049593217025n,
lower: 115792089237316195423570985008687907852589419931798687112530834793049593217025n
})
}
})

test('big mul', async () => {
const uints = await deployUints(sender)
{
Expand Down

0 comments on commit 9e084e8

Please sign in to comment.