Skip to content

Commit

Permalink
feat: integrate savings-usds/sky-psm (#723)
Browse files Browse the repository at this point in the history
* add testutil.TestCalcAmountIn

* simplify block timestamp

* use MulDivOverflow

* use common pool type
  • Loading branch information
minhnhathoang authored Feb 17, 2025
1 parent 7c14bb4 commit 14702ed
Show file tree
Hide file tree
Showing 32 changed files with 1,057 additions and 191 deletions.
6 changes: 3 additions & 3 deletions pkg/liquidity-source/maker/savingsdai/abis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

var (
potABI abi.ABI
savingsdaiABI abi.ABI
potABI abi.ABI
savingsABI abi.ABI
)

func init() {
Expand All @@ -17,7 +17,7 @@ func init() {
data []byte
}{
{&potABI, potJSON},
{&savingsdaiABI, savingsdaiJSON},
{&savingsABI, savingsJSON},
}

for _, b := range builder {
Expand Down
13 changes: 13 additions & 0 deletions pkg/liquidity-source/maker/savingsdai/abis/Pot.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
[
{
"inputs": [],
"name": "ssr",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
10 changes: 10 additions & 0 deletions pkg/liquidity-source/maker/savingsdai/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package savingsdai

type Config struct {
DexID string `json:"dexID"`
DepositToken string `json:"depositToken"`
SavingsToken string `json:"savingsToken"`
Pot string `json:"pot"`
// ssr (Sky Savings Rate) | dsr (DAI Savings Rate)
SavingsRateSymbol string `json:"savingsRateSymbol"`
}
30 changes: 15 additions & 15 deletions pkg/liquidity-source/maker/savingsdai/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,34 @@ package savingsdai
import (
"errors"

"github.com/KyberNetwork/blockchain-toolkit/number"
big256 "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/big256"
)

const (
DexType = "maker-savingsdai"

Dai = "0x6b175474e89094c44da98b954eedeac495271d0f"
Savingsdai = "0x83f20f44975d03b1b09e64809b757c47f942beea"
pot = "0x197e90f9fad81970ba7976f33cbd77088e5d7cf7"
potMethodRHO = "rho"
potMethodCHI = "chi"

potMethodDSR = "dsr"
potMethodRHO = "rho"
potMethodCHI = "chi"
savingsdaiMethodTotalAssets = "totalAssets"
savingsdaiMethodTotalSupply = "totalSupply"
savingsMethodTotalAssets = "totalAssets"
savingsMethodTotalSupply = "totalSupply"

blocktime = 12
Blocktime = 12
)

var (
one = number.TenPow(27)
ray = one
RAY = big256.TenPowInt(27)
)

var (
defaultGas = Gas{
Deposit: 161300,
Redeem: 235500,
savingsDAIDefaultGas = Gas{
Deposit: 160000,
Redeem: 146000,
}

savingsUSDSDefaultGas = Gas{
Deposit: 137000,
Redeem: 145000,
}
)

Expand Down
4 changes: 2 additions & 2 deletions pkg/liquidity-source/maker/savingsdai/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import _ "embed"
//go:embed abis/Pot.json
var potJSON []byte

//go:embed abis/SavingsDai.json
var savingsdaiJSON []byte
//go:embed abis/Savings.json
var savingsJSON []byte
47 changes: 28 additions & 19 deletions pkg/liquidity-source/maker/savingsdai/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,63 @@ var (
func rpow(x, n, base *uint256.Int) (*uint256.Int, error) {
if x.IsZero() {
if n.IsZero() {
return base, nil
return base.Clone(), nil
}

return number.Zero, nil
return number.Zero.Clone(), nil
}

z := x
if new(uint256.Int).Mod(n, number.Number_2).IsZero() {
z = base
var (
z uint256.Int
xx uint256.Int
xxRound uint256.Int
zx uint256.Int
zxRound uint256.Int
i uint256.Int
temp uint256.Int
)

if temp.Mod(n, number.Number_2).IsZero() {
z.Set(base)
}

half := new(uint256.Int).Div(base, number.Number_2)
for i := new(uint256.Int).Div(n, number.Number_2); i.Gt(number.Zero); i = new(uint256.Int).Div(i, number.Number_2) {
xx := new(uint256.Int).Mul(x, x)
for ; i.Gt(number.Zero); i.Div(&i, number.Number_2) {
xx.Mul(x, x)

if !new(uint256.Int).Div(xx, x).Eq(x) {
if !temp.Div(&xx, x).Eq(x) {
return nil, ErrOverflow
}

xxRound := new(uint256.Int).Add(xx, half)
if xxRound.Lt(xx) {
xxRound.Add(&xx, half)
if xxRound.Lt(&xx) {
return nil, ErrOverflow
}

x = new(uint256.Int).Div(xxRound, base)
if !new(uint256.Int).Mod(i, number.Number_2).IsZero() {
zx := new(uint256.Int).Mul(z, x)
x = new(uint256.Int).Div(&xxRound, base)
if !temp.Mod(&i, number.Number_2).IsZero() {
zx.Mul(&z, x)

if !x.IsZero() && !new(uint256.Int).Div(zx, x).Eq(z) {
if !x.IsZero() && !temp.Div(&zx, x).Eq(&z) {
return nil, ErrOverflow
}

zxRound := new(uint256.Int).Add(zx, half)
if zxRound.Lt(zx) {
zxRound.Add(&zx, half)
if zxRound.Lt(&zx) {
return nil, ErrOverflow
}

z = new(uint256.Int).Div(zxRound, base)
z.Div(&zxRound, base)
}
}

return z, nil
return &z, nil
}

func rmul(x, y *uint256.Int) (*uint256.Int, error) {
z, overflow := new(uint256.Int).MulOverflow(x, y)
if overflow {
return nil, ErrOverflow
}
return z.Div(z, one), nil
return z.Div(z, RAY), nil
}
78 changes: 78 additions & 0 deletions pkg/liquidity-source/maker/savingsdai/pool_list_updater.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package savingsdai

import (
"context"
"strings"

"github.com/KyberNetwork/ethrpc"
"github.com/KyberNetwork/logger"
"github.com/goccy/go-json"

"github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity"
poollist "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool/list"
)

type PoolListUpdater struct {
config *Config
ethrpcClient *ethrpc.Client
initialized bool
}

var _ = poollist.RegisterFactoryCE(DexType, NewPoolListUpdater)

func NewPoolListUpdater(config *Config, ethrpcClient *ethrpc.Client) *PoolListUpdater {
return &PoolListUpdater{
config: config,
ethrpcClient: ethrpcClient,
}
}

func (u *PoolListUpdater) GetNewPools(_ context.Context, metadataBytes []byte) ([]entity.Pool, []byte, error) {
logger.WithFields(logger.Fields{
"dexType": u.config.DexID,
}).Infof("Start updating pools list ...")
defer func() {
logger.WithFields(logger.Fields{
"dexType": u.config.DexID,
}).Infof("Finish updating pools list.")
}()

if u.initialized {
logger.WithFields(logger.Fields{
"dexType": u.config.DexID,
}).Infof("Pools have been initialized.")
return nil, metadataBytes, nil
}

staticExtra := StaticExtra{
Pot: u.config.Pot,
SavingsRateSymbol: u.config.SavingsRateSymbol,
}

staticExtraBytes, err := json.Marshal(staticExtra)
if err != nil {
return nil, nil, err
}

pool := entity.Pool{
Address: u.config.SavingsToken,
Exchange: u.config.DexID,
Type: DexType,
Reserves: entity.PoolReserves{"0", "0"},
Tokens: []*entity.PoolToken{
{
Address: strings.ToLower(u.config.DepositToken),
Swappable: true,
},
{
Address: strings.ToLower(u.config.SavingsToken),
Swappable: true,
},
},
StaticExtra: string(staticExtraBytes),
}

u.initialized = true

return []entity.Pool{pool}, metadataBytes, nil
}
85 changes: 85 additions & 0 deletions pkg/liquidity-source/maker/savingsdai/pool_list_updater_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package savingsdai

import (
"context"
"testing"

"github.com/KyberNetwork/ethrpc"
"github.com/ethereum/go-ethereum/common"
"github.com/goccy/go-json"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

poolpkg "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool"
"github.com/KyberNetwork/kyberswap-dex-lib/pkg/valueobject"
)

type PoolListUpdaterTestSuite struct {
suite.Suite
}

func (ts *PoolListUpdaterTestSuite) TestGetNewPools() {
rpcClientByChainID := map[valueobject.ChainID]*ethrpc.Client{
1: ethrpc.New("https://ethereum.kyberengineering.io").
SetMulticallContract(common.HexToAddress("0x5ba1e12693dc8f9c48aad8770482f4739beed696")),
}

testCases := []struct {
chainID valueobject.ChainID
config Config
}{
{
chainID: valueobject.ChainIDEthereum,
config: Config{
DepositToken: "0x6b175474e89094c44da98b954eedeac495271d0f",
SavingsToken: "0x83f20f44975d03b1b09e64809b757c47f942beea",
Pot: "0x197e90f9fad81970ba7976f33cbd77088e5d7cf7",
SavingsRateSymbol: "dsr",
},
},
{
chainID: valueobject.ChainIDEthereum,
config: Config{
DepositToken: "0xdc035d45d973e3ec169d2276ddab16f1e407384f",
SavingsToken: "0xa3931d71877c0e7a3148cb7eb4463524fec27fbd",
Pot: "0xa3931d71877c0e7a3148cb7eb4463524fec27fbd",
SavingsRateSymbol: "ssr",
},
},
}

for _, tc := range testCases {
ts.T().Run(tc.config.DexID, func(t *testing.T) {
updater := PoolListUpdater{
config: &tc.config,
ethrpcClient: rpcClientByChainID[tc.chainID],
initialized: false,
}

tracker := NewPoolTracker(
&tc.config,
rpcClientByChainID[tc.chainID],
)

pools, _, err := updater.GetNewPools(context.Background(), nil)
require.NoError(t, err)
require.NotNil(t, pools)

for _, pool := range pools {
entityPool, err := tracker.GetNewPoolState(context.Background(), pool, poolpkg.GetNewPoolStateParams{})
require.NoError(t, err)
require.NotNil(t, entityPool)

prettyJSON, err := json.MarshalIndent(entityPool, "", " ")
require.NoError(t, err)
require.NotNil(t, pools)
t.Log(string(prettyJSON))
}
})
}
}

func TestPoolListUpdaterTestSuite(t *testing.T) {
// t.Skip("Skipping testing in CI environment")
suite.Run(t, new(PoolListUpdaterTestSuite))
}
Loading

0 comments on commit 14702ed

Please sign in to comment.