Skip to content

Commit

Permalink
define safety balances slice
Browse files Browse the repository at this point in the history
  • Loading branch information
sunspirit99 committed Jan 2, 2025
1 parent 0fb97c8 commit 53197bc
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 128 deletions.
4 changes: 2 additions & 2 deletions pkg/liquidity-source/balancer-v3/hooks/directional_fee.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func NewDirectionalFeeHook(staticSwapFeePercentage *uint256.Int) *directionalFee
}

func (h *directionalFeeHook) OnComputeDynamicSwapFeePercentage(param shared.PoolSwapParams) (bool, *uint256.Int, error) {
calculatedSwapFeePercentage, err := h.calculatedExpectedSwapFeePercentage(param.BalancesLiveScaled18[param.IndexIn],
param.BalancesLiveScaled18[param.IndexOut], param.AmountGivenScaled18)
calculatedSwapFeePercentage, err := h.calculatedExpectedSwapFeePercentage(param.BalancesLiveScaled18.Get(param.IndexIn),
param.BalancesLiveScaled18.Get(param.IndexOut), param.AmountGivenScaled18)
if err != nil {
return false, nil, err
}
Expand Down
70 changes: 33 additions & 37 deletions pkg/liquidity-source/balancer-v3/math/stable_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package math

import (
"errors"
"sync"

"github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer-v3/shared"
"github.com/holiman/uint256"
)

Expand All @@ -16,17 +16,15 @@ var (

var StableMath *stableMath

type stableMath struct {
mu sync.RWMutex
}
type stableMath struct{}

func init() {
StableMath = &stableMath{}
}

func (s *stableMath) ComputeOutGivenExactIn(
amplificationParameter *uint256.Int,
balances []*uint256.Int,
balances *shared.Balances,
tokenIndexIn, tokenIndexOut int,
tokenAmountIn, invariant *uint256.Int,
) (amountOut *uint256.Int, err error) {
Expand All @@ -42,25 +40,26 @@ func (s *stableMath) ComputeOutGivenExactIn(
// P = product of final balances but y //
**************************************************************************************************************/

s.mu.Lock()
defer s.mu.Unlock()

balances[tokenIndexIn], err = FixPoint.Add(balances[tokenIndexIn], tokenAmountIn)
balanceInTmp, err := FixPoint.Add(balances.Get(tokenIndexIn), tokenAmountIn)
if err != nil {
return nil, err
}

balances.Update(tokenIndexIn, balanceInTmp)

finalBalanceOut, err := s.ComputeBalance(amplificationParameter, balances, invariant, tokenIndexOut)
if err != nil {
return nil, err
}

balances[tokenIndexIn], err = FixPoint.Sub(balances[tokenIndexIn], tokenAmountIn)
balanceInTmp, err = FixPoint.Sub(balances.Get(tokenIndexIn), tokenAmountIn)
if err != nil {
return nil, err
}

amountOut, err = FixPoint.Sub(balances[tokenIndexOut], finalBalanceOut)
balances.Update(tokenIndexIn, balanceInTmp)

amountOut, err = FixPoint.Sub(balances.Get(tokenIndexOut), finalBalanceOut)
if err != nil {
return nil, err
}
Expand All @@ -72,7 +71,7 @@ func (s *stableMath) ComputeOutGivenExactIn(

func (s *stableMath) ComputeInGivenExactOut(
amplificationParameter *uint256.Int,
balances []*uint256.Int,
balances *shared.Balances,
tokenIndexIn, tokenIndexOut int,
tokenAmountOut, invariant *uint256.Int,
) (amountIn *uint256.Int, err error) {
Expand All @@ -88,25 +87,26 @@ func (s *stableMath) ComputeInGivenExactOut(
// P = product of final balances but x //
**************************************************************************************************************/

s.mu.Lock()
defer s.mu.Unlock()

balances[tokenIndexOut], err = FixPoint.Sub(balances[tokenIndexOut], tokenAmountOut)
balanceOutTmp, err := FixPoint.Sub(balances.Get(tokenIndexOut), tokenAmountOut)
if err != nil {
return nil, err
}

balances.Update(tokenIndexOut, balanceOutTmp)

finalBalanceIn, err := s.ComputeBalance(amplificationParameter, balances, invariant, tokenIndexIn)
if err != nil {
return nil, err
}

balances[tokenIndexOut], err = FixPoint.Add(balances[tokenIndexOut], tokenAmountOut)
balanceOutTmp, err = FixPoint.Add(balances.Get(tokenIndexOut), tokenAmountOut)
if err != nil {
return nil, err
}

amountIn, err = FixPoint.Sub(finalBalanceIn, balances[tokenIndexIn])
balances.Update(tokenIndexOut, balanceOutTmp)

amountIn, err = FixPoint.Sub(finalBalanceIn, balances.Get(tokenIndexIn))
if err != nil {
return nil, err
}
Expand All @@ -118,28 +118,28 @@ func (s *stableMath) ComputeInGivenExactOut(

func (s *stableMath) ComputeBalance(
amplificationParameter *uint256.Int,
balances []*uint256.Int,
balances *shared.Balances,
invariant *uint256.Int,
tokenIndex int,
) (*uint256.Int, error) {
numTokens := uint256.NewInt(uint64(len(balances)))
numTokens := uint256.NewInt(uint64(balances.Len()))

// A * n
ampTimesN := new(uint256.Int).Mul(amplificationParameter, numTokens)

sumBalances := new(uint256.Int).Set(balances[0])
balanceProduct := new(uint256.Int).Mul(balances[0], numTokens)
sumBalances := new(uint256.Int).Set(balances.Get(0))
balanceProduct := new(uint256.Int).Mul(balances.Get(0), numTokens)

// (P_D * x_j * n) / D
mulResult := new(uint256.Int)
for j := 1; j < len(balances); j++ {
mulResult.Mul(balanceProduct, balances[j])
for j := 1; j < balances.Len(); j++ {
mulResult.Mul(balanceProduct, balances.Get(j))
mulResult.Mul(mulResult, numTokens)
balanceProduct.Div(mulResult, invariant)
sumBalances.Add(sumBalances, balances[j])
sumBalances.Add(sumBalances, balances.Get(j))
}

sumBalances.Sub(sumBalances, balances[tokenIndex])
sumBalances.Sub(sumBalances, balances.Get(tokenIndex))

invariantSquared := new(uint256.Int).Mul(invariant, invariant)

Expand All @@ -152,7 +152,7 @@ func (s *stableMath) ComputeBalance(
return nil, err
}

c.Mul(c, balances[tokenIndex])
c.Mul(c, balances.Get(tokenIndex))

// b = S + (D * AP)/An
b := new(uint256.Int).Mul(invariant, _AMP_PRECISION)
Expand Down Expand Up @@ -206,7 +206,7 @@ func (s *stableMath) ComputeBalance(
return nil, ErrStableComputeBalanceDidNotConverge
}

func (s *stableMath) ComputeInvariant(amplificationParameter *uint256.Int, balances []*uint256.Int) (*uint256.Int, error) {
func (s *stableMath) ComputeInvariant(amplificationParameter *uint256.Int, balances *shared.Balances) (*uint256.Int, error) {
/**********************************************************************************************
// invariant //
// D = invariant D^(n+1) //
Expand All @@ -216,14 +216,12 @@ func (s *stableMath) ComputeInvariant(amplificationParameter *uint256.Int, balan
// n = number of tokens //
**********************************************************************************************/

numTokens := uint256.NewInt(uint64(len(balances)))
numTokens := uint256.NewInt(uint64(balances.Len()))
sum := uint256.NewInt(0)

s.mu.RLock()
for i := range balances {
sum.Add(sum, balances[i])
for i := 0; i < balances.Len(); i++ {
sum.Add(sum, balances.Get(i))
}
s.mu.RUnlock()

if sum.IsZero() {
return sum, nil
Expand All @@ -245,14 +243,12 @@ func (s *stableMath) ComputeInvariant(amplificationParameter *uint256.Int, balan
// D_P = D^(n+1)/(n^n * P)
D_P.Set(invariant)

s.mu.RLock()
for _, balance := range balances {
for i := 0; i < balances.Len(); i++ {
// D_P = D_P * D / (x_i * n)
tmp.Mul(balance, numTokens)
tmp.Mul(balances.Get(i), numTokens)
D_P.Mul(D_P, invariant)
D_P.Div(D_P, tmp)
}
s.mu.RUnlock()

// (A * n * S / AP + D_P * n) * D
numer.Mul(ampTimesN, sum)
Expand Down
49 changes: 25 additions & 24 deletions pkg/liquidity-source/balancer-v3/math/stable_math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package math
import (
"testing"

"github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/balancer-v3/shared"
"github.com/holiman/uint256"
"github.com/stretchr/testify/assert"
)
Expand All @@ -11,48 +12,48 @@ func TestStableMath_ComputeInvariant(t *testing.T) {
tests := []struct {
name string
amp *uint256.Int
balances []*uint256.Int
balances *shared.Balances
expectedInvariant *uint256.Int
expectedErr error
}{
{
name: "Basic 2 token pool",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1000000),
uint256.NewInt(1000000),
},
}),
expectedInvariant: uint256.NewInt(2000000),
expectedErr: nil,
},
{
name: "Imbalanced 2 token pool",
amp: uint256.NewInt(200000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.MustFromDecimal("340867122491122140643"),
uint256.MustFromDecimal("384610409069784884043"),
},
}),
expectedInvariant: uint256.MustFromDecimal("725470946757739599230"),
expectedErr: nil,
},
{
name: "3 token pool",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1000000),
uint256.NewInt(1000000),
uint256.NewInt(1000000),
},
}),
expectedInvariant: uint256.NewInt(3000000),
expectedErr: nil,
},
{
name: "Zero balances",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(0),
uint256.NewInt(0),
},
}),
expectedInvariant: uint256.NewInt(0),
expectedErr: nil,
},
Expand All @@ -76,7 +77,7 @@ func TestStableMath_ComputeBalance(t *testing.T) {
tests := []struct {
name string
amp *uint256.Int
balances []*uint256.Int
balances *shared.Balances
invariant *uint256.Int
tokenIndex int
expectedBalance *uint256.Int
Expand All @@ -85,10 +86,10 @@ func TestStableMath_ComputeBalance(t *testing.T) {
{
name: "Balanced 2 token pool",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1000000),
uint256.NewInt(1000000),
},
}),
invariant: uint256.NewInt(2000000),
tokenIndex: 0,
expectedBalance: uint256.NewInt(1000001),
Expand All @@ -97,10 +98,10 @@ func TestStableMath_ComputeBalance(t *testing.T) {
{
name: "Imbalanced 2 token pool",
amp: uint256.NewInt(200000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.MustFromDecimal("340867122491122140643"),
uint256.MustFromDecimal("384610409069784884043"),
},
}),
invariant: uint256.MustFromDecimal("725470946757739599230"),
tokenIndex: 1,
expectedBalance: uint256.MustFromDecimal("384610409069784884044"),
Expand All @@ -126,7 +127,7 @@ func TestStableMath_ComputeOutGivenExactIn(t *testing.T) {
tests := []struct {
name string
amp *uint256.Int
balances []*uint256.Int
balances *shared.Balances
tokenIndexIn int
tokenIndexOut int
tokenAmountIn *uint256.Int
Expand All @@ -137,10 +138,10 @@ func TestStableMath_ComputeOutGivenExactIn(t *testing.T) {
{
name: "Equal pool swap",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1000000),
uint256.NewInt(1000000),
},
}),
tokenIndexIn: 0,
tokenIndexOut: 1,
tokenAmountIn: uint256.NewInt(100),
Expand All @@ -151,10 +152,10 @@ func TestStableMath_ComputeOutGivenExactIn(t *testing.T) {
{
name: "Imbalanced pool swap",
amp: uint256.NewInt(100),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1500000),
uint256.NewInt(500000),
},
}),
tokenIndexIn: 0,
tokenIndexOut: 1,
tokenAmountIn: uint256.NewInt(100),
Expand Down Expand Up @@ -189,7 +190,7 @@ func TestStableMath_ComputeInGivenExactOut(t *testing.T) {
tests := []struct {
name string
amp *uint256.Int
balances []*uint256.Int
balances *shared.Balances
tokenIndexIn int
tokenIndexOut int
tokenAmountIn *uint256.Int
Expand All @@ -200,10 +201,10 @@ func TestStableMath_ComputeInGivenExactOut(t *testing.T) {
{
name: "Equal pool swap",
amp: uint256.NewInt(1000000),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1000000),
uint256.NewInt(1000000),
},
}),
tokenIndexIn: 0,
tokenIndexOut: 1,
tokenAmountIn: uint256.NewInt(100),
Expand All @@ -214,10 +215,10 @@ func TestStableMath_ComputeInGivenExactOut(t *testing.T) {
{
name: "Imbalanced pool swap",
amp: uint256.NewInt(100),
balances: []*uint256.Int{
balances: shared.NewBalances([]*uint256.Int{
uint256.NewInt(1500000),
uint256.NewInt(500000),
},
}),
tokenIndexIn: 0,
tokenIndexOut: 1,
tokenAmountIn: uint256.NewInt(100),
Expand Down
Loading

0 comments on commit 53197bc

Please sign in to comment.