Skip to content

Commit

Permalink
Merge pull request #180 from gnoswap-labs/GSW-807-protocol-fees
Browse files Browse the repository at this point in the history
GSW-807 protocol fees
  • Loading branch information
notJoon authored Feb 26, 2024
2 parents c88f1f9 + 4e329eb commit 19124a6
Show file tree
Hide file tree
Showing 21 changed files with 564 additions and 254 deletions.
13 changes: 9 additions & 4 deletions consts/consts.gno
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import (
"std"
)

// MOST LIKELY FIXED, BUT CHANGABLE VIA GOVERNANCE
var (
PROTOCOL_FEE_ROUTER = 15 // 0.15%
)

// GNOSWAP SERVICE
const (
GNOSWAP_ADMIN std.Address = "g12l9splsyngcgefrwa52x5a7scc29e9v086m6p4" // GSA, r3v4_xxx: CHANGE WHEN DEPLOYING TO OFFICIAL NETWORK
GNOSWAP_ADMIN std.Address = "g12l9splsyngcgefrwa52x5a7scc29e9v086m6p4" // GSA, r3v4_xxx: CHANGE WHEN DEPLOYING TO OFFICIAL NETWORK
FEE_COLLECTOR std.Address = "g12l9splsyngcgefrwa52x5a7scc29e9v086m6p4" // SAME AS GSA FOR NOW, r3v4_xxx: CHANGE WHEN DEPLOYING TO OFFICIAL NETWORK

INTERNAL_REWARD_ACCOUNT std.Address = "g1paqttvcjcluuya9n9twyw7yacv54mt7ld3gvzm" // IRA, r3v4_xxx: CHANGE WHEN DEPLOYING TO OFFICIAL NETWORK

// 500 GNS as creation fee (r3v4_xxx: 500 or 500_000_000)
POOL_CREATION_FEE uint64 = 500
// POOL_CREATION_FEE uint64 = 500_000_000
POOL_CREATION_FEE uint64 = 500_000_000
)

// WRAP & UNWRAP
Expand Down
119 changes: 0 additions & 119 deletions pool/pool.gno
Original file line number Diff line number Diff line change
Expand Up @@ -535,125 +535,6 @@ func CollectProtocol(
return amount0, amount1
}

func (pool *Pool) modifyPosition(params ModifyPositionParams) (PositionInfo, bigint, bigint) {
position := pool.updatePosition(
params.owner,
params.tickLower,
params.tickUpper,
params.liquidityDelta,
pool.slot0.tick,
)

var amount0, amount1 bigint

if params.liquidityDelta != 0 {
if pool.slot0.tick < params.tickLower {
amount0 = sqrtPriceMathGetAmount0Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)
} else if pool.slot0.tick < params.tickUpper {
liquidityBefore := pool.liquidity

amount0 = sqrtPriceMathGetAmount0Delta(
pool.slot0.sqrtPriceX96,
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)

amount1 = sqrtPriceMathGetAmount1Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
pool.slot0.sqrtPriceX96,
params.liquidityDelta,
)

pool.liquidity = liquidityMathAddDelta(liquidityBefore, params.liquidityDelta)

} else {
amount1 = sqrtPriceMathGetAmount1Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)
}
}

return position, amount0, amount1
}

func (pool *Pool) updatePosition(
owner std.Address,
tickLower int32,
tickUpper int32,
liquidityDelta bigint,
tick int32,
) PositionInfo {
var _feeGrowthGlobal0X128 bigint = pool.feeGrowthGlobal0X128
var _feeGrowthGlobal1X128 bigint = pool.feeGrowthGlobal1X128

var flippedLower, flippedUpper bool
if liquidityDelta != 0 {
flippedLower = pool.tickUpdate(
tickLower,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
false,
pool.maxLiquidityPerTick,
)

flippedUpper = pool.tickUpdate(
tickUpper,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
true,
pool.maxLiquidityPerTick,
)

if flippedLower {
pool.tickBitmapFlipTick(tickLower, pool.tickSpacing)
}

if flippedUpper {
pool.tickBitmapFlipTick(tickUpper, pool.tickSpacing)
}
}

// NO LIQ, ONLY BURN 0

feeGrowthInside0X128, feeGrowthInside1X128 := pool.tickGetFeeGrowthInside(
tickLower,
tickUpper,
tick,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
)

positionKey := positionGetKey(owner, tickLower, tickUpper)

position := pool.positionUpdateWithKey(
positionKey,
liquidityDelta,
feeGrowthInside0X128,
feeGrowthInside1X128,
)

if liquidityDelta < 0 {
if flippedLower {
pool.tickClear(tickLower)
}

if flippedUpper {
pool.tickClear(tickUpper)
}
}
return position
}

func (pool *Pool) saveProtocolFees(amount0, amount1 bigint) (bigint, bigint) {
if amount0 > 0 && amount0 == pool.protocolFees.token0 {
amount0--
Expand Down
2 changes: 1 addition & 1 deletion pool/pool_manager.gno
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

"gno.land/r/demo/consts"

gns "gno.land/r/demo/gns"
"gno.land/r/demo/gns"
)

var (
Expand Down
52 changes: 52 additions & 0 deletions pool/position_modify.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package pool

import (
"gno.land/p/demo/common"
)

func (pool *Pool) modifyPosition(params ModifyPositionParams) (PositionInfo, bigint, bigint) {
position := pool.updatePosition(
params.owner,
params.tickLower,
params.tickUpper,
params.liquidityDelta,
pool.slot0.tick,
)

var amount0, amount1 bigint

if params.liquidityDelta != 0 {
if pool.slot0.tick < params.tickLower {
amount0 = sqrtPriceMathGetAmount0Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)
} else if pool.slot0.tick < params.tickUpper {
liquidityBefore := pool.liquidity

amount0 = sqrtPriceMathGetAmount0Delta(
pool.slot0.sqrtPriceX96,
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)

amount1 = sqrtPriceMathGetAmount1Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
pool.slot0.sqrtPriceX96,
params.liquidityDelta,
)

pool.liquidity = liquidityMathAddDelta(liquidityBefore, params.liquidityDelta)

} else {
amount1 = sqrtPriceMathGetAmount1Delta(
common.TickMathGetSqrtRatioAtTick(params.tickLower),
common.TickMathGetSqrtRatioAtTick(params.tickUpper),
params.liquidityDelta,
)
}
}

return position, amount0, amount1
}
77 changes: 77 additions & 0 deletions pool/position_update.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package pool

import (
"std"
)

func (pool *Pool) updatePosition(
owner std.Address,
tickLower int32,
tickUpper int32,
liquidityDelta bigint,
tick int32,
) PositionInfo {
var _feeGrowthGlobal0X128 bigint = pool.feeGrowthGlobal0X128
var _feeGrowthGlobal1X128 bigint = pool.feeGrowthGlobal1X128

var flippedLower, flippedUpper bool
if liquidityDelta != 0 {
flippedLower = pool.tickUpdate(
tickLower,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
false,
pool.maxLiquidityPerTick,
)

flippedUpper = pool.tickUpdate(
tickUpper,
tick,
liquidityDelta,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
true,
pool.maxLiquidityPerTick,
)

if flippedLower {
pool.tickBitmapFlipTick(tickLower, pool.tickSpacing)
}

if flippedUpper {
pool.tickBitmapFlipTick(tickUpper, pool.tickSpacing)
}
}

// NO LIQ, ONLY BURN 0

feeGrowthInside0X128, feeGrowthInside1X128 := pool.tickGetFeeGrowthInside(
tickLower,
tickUpper,
tick,
_feeGrowthGlobal0X128,
_feeGrowthGlobal1X128,
)

positionKey := positionGetKey(owner, tickLower, tickUpper)

position := pool.positionUpdateWithKey(
positionKey,
liquidityDelta,
feeGrowthInside0X128,
feeGrowthInside1X128,
)

if liquidityDelta < 0 {
if flippedLower {
pool.tickClear(tickLower)
}

if flippedUpper {
pool.tickClear(tickUpper)
}
}
return position
}
50 changes: 50 additions & 0 deletions pool/withdrawal_fee.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package pool

import (
"std"

"gno.land/r/demo/consts"

"gno.land/p/demo/ufmt"
)

var (
withdrawalFee = bigint(1)
)

func HandleWithdrawalFee(
tokenId uint64,
token0Path string,
amount0 bigint,
token1Path string,
amount1 bigint,
) (bigint, bigint) {
requirePrevRealmPath(consts.POSITION_PATH, ufmt.Sprintf("[POOL] withdrawal_fee.gno__HandleWithdrawFee() || expected PrevRealmPath(%s), got %s", consts.POSITION_PATH, PrevRealmPath()))

if withdrawalFee == 0 {
return amount0, amount1
}

feeAmount0 := amount0 * withdrawalFee / bigint(100)
feeAmount1 := amount1 * withdrawalFee / bigint(100)

ok := transferFromByRegisterCall(token0Path, GetOrigCaller(), consts.FEE_COLLECTOR, uint64(feeAmount0))
require(ok, ufmt.Sprintf("[POOL] withdrawal_fee.gno__HandleWithdrawFee() || expected transferFromByRegisterCall(%s, %s, %s, %s) == true", token0Path, GetOrigCaller(), consts.FEE_COLLECTOR, feeAmount0))

ok = transferFromByRegisterCall(token1Path, GetOrigCaller(), consts.FEE_COLLECTOR, uint64(feeAmount1))
require(ok, ufmt.Sprintf("[POOL] withdrawal_fee.gno__HandleWithdrawFee() || expected transferFromByRegisterCall(%s, %s, %s, %s) == true", token1Path, GetOrigCaller(), consts.FEE_COLLECTOR, feeAmount1))

return amount0 - feeAmount0, amount1 - feeAmount1
}

func SetWithdrawalFee(fee bigint) {
// MUST BE ORIGIN CALL
std.AssertOriginCall()

// MUST BE ADMIN
require(isAdmin(GetOrigCaller()), ufmt.Sprintf("[POOL] withdrawal_fee.gno__SetFeeProtocol() || caller(%s) must be admin", GetOrigCaller()))

require(fee >= 0, ufmt.Sprintf("[POOL] withdrawal_fee.gno__SetFeeProtocol() || fee(%d) must be >= 0", fee))

withdrawalFee = fee
}
8 changes: 8 additions & 0 deletions position/_TEST_INIT_basic_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"gno.land/r/demo/wugnot"

"gno.land/r/demo/gnft"

pl "gno.land/r/demo/pool"
)

var (
Expand Down Expand Up @@ -108,3 +110,9 @@ func isOwner(t *testing.T, tokenId uint64, addr std.Address) bool {
t.Errorf("expected owner %v, got %v", addr, owner)
return false
}

func getPoolFromLpTokenId(lpTokenId uint64) *pl.Pool {
position := positions[lpTokenId]

return pl.GetPoolFromPoolPath(position.poolKey)
}
Loading

0 comments on commit 19124a6

Please sign in to comment.