From b0f87496899577a823fe76059bae08c96f82d15f Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 10:17:14 +0200 Subject: [PATCH 01/17] make a fork from uniswap --- pkg/source/crowdswapv2/abis.go | 34 + .../crowdswapv2/abis/UniswapV2Factory.json | 193 +++++ .../crowdswapv2/abis/UniswapV2Pair.json | 713 ++++++++++++++++++ pkg/source/crowdswapv2/config.go | 8 + pkg/source/crowdswapv2/constant.go | 25 + pkg/source/crowdswapv2/embed.go | 9 + pkg/source/crowdswapv2/formula.go | 533 +++++++++++++ pkg/source/crowdswapv2/math.go | 34 + pkg/source/crowdswapv2/pool_simulator.go | 127 ++++ pkg/source/crowdswapv2/pool_tracker.go | 55 ++ pkg/source/crowdswapv2/pools_list_updater.go | 183 +++++ pkg/source/crowdswapv2/type.go | 24 + 12 files changed, 1938 insertions(+) create mode 100644 pkg/source/crowdswapv2/abis.go create mode 100644 pkg/source/crowdswapv2/abis/UniswapV2Factory.json create mode 100644 pkg/source/crowdswapv2/abis/UniswapV2Pair.json create mode 100644 pkg/source/crowdswapv2/config.go create mode 100644 pkg/source/crowdswapv2/constant.go create mode 100644 pkg/source/crowdswapv2/embed.go create mode 100644 pkg/source/crowdswapv2/formula.go create mode 100644 pkg/source/crowdswapv2/math.go create mode 100644 pkg/source/crowdswapv2/pool_simulator.go create mode 100644 pkg/source/crowdswapv2/pool_tracker.go create mode 100644 pkg/source/crowdswapv2/pools_list_updater.go create mode 100644 pkg/source/crowdswapv2/type.go diff --git a/pkg/source/crowdswapv2/abis.go b/pkg/source/crowdswapv2/abis.go new file mode 100644 index 000000000..61da017f1 --- /dev/null +++ b/pkg/source/crowdswapv2/abis.go @@ -0,0 +1,34 @@ +package uniswap + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/accounts/abi" +) + +var ( + uniswapV2PairABI abi.ABI + uniswapV2FactoryABI abi.ABI +) + +func init() { + builder := []struct { + ABI *abi.ABI + data []byte + }{ + { + &uniswapV2PairABI, pairABIJson, + }, + { + &uniswapV2FactoryABI, factoryABIJson, + }, + } + + for _, b := range builder { + var err error + *b.ABI, err = abi.JSON(bytes.NewReader(b.data)) + if err != nil { + panic(err) + } + } +} diff --git a/pkg/source/crowdswapv2/abis/UniswapV2Factory.json b/pkg/source/crowdswapv2/abis/UniswapV2Factory.json new file mode 100644 index 000000000..a2f132767 --- /dev/null +++ b/pkg/source/crowdswapv2/abis/UniswapV2Factory.json @@ -0,0 +1,193 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeToSetter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "name": "setFeeToSetter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/pkg/source/crowdswapv2/abis/UniswapV2Pair.json b/pkg/source/crowdswapv2/abis/UniswapV2Pair.json new file mode 100644 index 000000000..53582c1ed --- /dev/null +++ b/pkg/source/crowdswapv2/abis/UniswapV2Pair.json @@ -0,0 +1,713 @@ +[ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint112", + "name": "reserve0", + "type": "uint112" + }, + { + "indexed": false, + "internalType": "uint112", + "name": "reserve1", + "type": "uint112" + } + ], + "name": "Sync", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MINIMUM_LIQUIDITY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint112", + "name": "_reserve0", + "type": "uint112" + }, + { + "internalType": "uint112", + "name": "_reserve1", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "_blockTimestampLast", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "kLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price0CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price1CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "skim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "swap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "sync", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token0", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/pkg/source/crowdswapv2/config.go b/pkg/source/crowdswapv2/config.go new file mode 100644 index 000000000..76d8df051 --- /dev/null +++ b/pkg/source/crowdswapv2/config.go @@ -0,0 +1,8 @@ +package uniswap + +type Config struct { + DexID string `json:"dexID"` + SwapFee float64 `json:"swapFee"` + FactoryAddress string `json:"factoryAddress"` + NewPoolLimit int `json:"newPoolLimit"` +} diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go new file mode 100644 index 000000000..fb2f27ebb --- /dev/null +++ b/pkg/source/crowdswapv2/constant.go @@ -0,0 +1,25 @@ +package uniswap + +import "math/big" + +const ( + DexTypeUniswap = "uniswap" + defaultTokenWeight = 50 + reserveZero = "0" +) + +const ( + factoryMethodGetPair = "allPairs" + factoryMethodAllPairsLength = "allPairsLength" + pairMethodToken0 = "token0" + pairMethodToken1 = "token1" + pairMethodGetReserves = "getReserves" +) + +var ( + zeroBI = big.NewInt(0) + defaultGas = Gas{SwapBase: 60000, SwapNonBase: 102000} + defaultSwapFee = "2" + bOne = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) + bOneFloat, _ = new(big.Float).SetString("1000000000000000000") +) diff --git a/pkg/source/crowdswapv2/embed.go b/pkg/source/crowdswapv2/embed.go new file mode 100644 index 000000000..85dfd525c --- /dev/null +++ b/pkg/source/crowdswapv2/embed.go @@ -0,0 +1,9 @@ +package uniswap + +import _ "embed" + +//go:embed abis/UniswapV2Pair.json +var pairABIJson []byte + +//go:embed abis/UniswapV2Factory.json +var factoryABIJson []byte diff --git a/pkg/source/crowdswapv2/formula.go b/pkg/source/crowdswapv2/formula.go new file mode 100644 index 000000000..f1cb7fdc7 --- /dev/null +++ b/pkg/source/crowdswapv2/formula.go @@ -0,0 +1,533 @@ +package uniswap + +import ( + "errors" + "math/big" +) + +var MinPrecision = uint(32) +var MaxPrecision = uint(127) + +var Fixed1 *big.Int +var Fixed2 *big.Int + +var Ln2Numerator *big.Int +var Ln2Denominator *big.Int + +var OptLogMaxVal *big.Int +var OptExpMaxVal *big.Int + +var One *big.Int +var Zero *big.Int + +var maxExpArray []*big.Int + +func NewBig(s string) (res *big.Int) { + res, _ = new(big.Int).SetString(s, 0) + return res +} + +func init() { + Fixed1 = NewBig("0x080000000000000000000000000000000") + Fixed2 = NewBig("0x100000000000000000000000000000000") + + Ln2Numerator = NewBig("0x3f80fe03f80fe03f80fe03f80fe03f8") + Ln2Denominator = NewBig("0x5b9de1d10bf4103d647b0955897ba80") + + OptLogMaxVal = NewBig("0x15bf0a8b1457695355fb8ac404e7a79e3") + OptExpMaxVal = NewBig("0x800000000000000000000000000000000") + + One = big.NewInt(1) + Zero = big.NewInt(0) + + maxExpArray = make([]*big.Int, 128) + + maxExpArray[32] = NewBig("0x1c35fedd14ffffffffffffffffffffffff") + maxExpArray[33] = NewBig("0x1b0ce43b323fffffffffffffffffffffff") + maxExpArray[34] = NewBig("0x19f0028ec1ffffffffffffffffffffffff") + maxExpArray[35] = NewBig("0x18ded91f0e7fffffffffffffffffffffff") + maxExpArray[36] = NewBig("0x17d8ec7f0417ffffffffffffffffffffff") + maxExpArray[37] = NewBig("0x16ddc6556cdbffffffffffffffffffffff") + maxExpArray[38] = NewBig("0x15ecf52776a1ffffffffffffffffffffff") + maxExpArray[39] = NewBig("0x15060c256cb2ffffffffffffffffffffff") + maxExpArray[40] = NewBig("0x1428a2f98d72ffffffffffffffffffffff") + maxExpArray[41] = NewBig("0x13545598e5c23fffffffffffffffffffff") + maxExpArray[42] = NewBig("0x1288c4161ce1dfffffffffffffffffffff") + maxExpArray[43] = NewBig("0x11c592761c666fffffffffffffffffffff") + maxExpArray[44] = NewBig("0x110a688680a757ffffffffffffffffffff") + maxExpArray[45] = NewBig("0x1056f1b5bedf77ffffffffffffffffffff") + maxExpArray[46] = NewBig("0x0faadceceeff8bffffffffffffffffffff") + maxExpArray[47] = NewBig("0x0f05dc6b27edadffffffffffffffffffff") + maxExpArray[48] = NewBig("0x0e67a5a25da4107fffffffffffffffffff") + maxExpArray[49] = NewBig("0x0dcff115b14eedffffffffffffffffffff") + maxExpArray[50] = NewBig("0x0d3e7a392431239fffffffffffffffffff") + maxExpArray[51] = NewBig("0x0cb2ff529eb71e4fffffffffffffffffff") + maxExpArray[52] = NewBig("0x0c2d415c3db974afffffffffffffffffff") + maxExpArray[53] = NewBig("0x0bad03e7d883f69bffffffffffffffffff") + maxExpArray[54] = NewBig("0x0b320d03b2c343d5ffffffffffffffffff") + maxExpArray[55] = NewBig("0x0abc25204e02828dffffffffffffffffff") + maxExpArray[56] = NewBig("0x0a4b16f74ee4bb207fffffffffffffffff") + maxExpArray[57] = NewBig("0x09deaf736ac1f569ffffffffffffffffff") + maxExpArray[58] = NewBig("0x0976bd9952c7aa957fffffffffffffffff") + maxExpArray[59] = NewBig("0x09131271922eaa606fffffffffffffffff") + maxExpArray[60] = NewBig("0x08b380f3558668c46fffffffffffffffff") + maxExpArray[61] = NewBig("0x0857ddf0117efa215bffffffffffffffff") + maxExpArray[62] = NewBig("0x07ffffffffffffffffffffffffffffffff") + maxExpArray[63] = NewBig("0x07abbf6f6abb9d087fffffffffffffffff") + maxExpArray[64] = NewBig("0x075af62cbac95f7dfa7fffffffffffffff") + maxExpArray[65] = NewBig("0x070d7fb7452e187ac13fffffffffffffff") + maxExpArray[66] = NewBig("0x06c3390ecc8af379295fffffffffffffff") + maxExpArray[67] = NewBig("0x067c00a3b07ffc01fd6fffffffffffffff") + maxExpArray[68] = NewBig("0x0637b647c39cbb9d3d27ffffffffffffff") + maxExpArray[69] = NewBig("0x05f63b1fc104dbd39587ffffffffffffff") + maxExpArray[70] = NewBig("0x05b771955b36e12f7235ffffffffffffff") + maxExpArray[71] = NewBig("0x057b3d49dda84556d6f6ffffffffffffff") + maxExpArray[72] = NewBig("0x054183095b2c8ececf30ffffffffffffff") + maxExpArray[73] = NewBig("0x050a28be635ca2b888f77fffffffffffff") + maxExpArray[74] = NewBig("0x04d5156639708c9db33c3fffffffffffff") + maxExpArray[75] = NewBig("0x04a23105873875bd52dfdfffffffffffff") + maxExpArray[76] = NewBig("0x0471649d87199aa990756fffffffffffff") + maxExpArray[77] = NewBig("0x04429a21a029d4c1457cfbffffffffffff") + maxExpArray[78] = NewBig("0x0415bc6d6fb7dd71af2cb3ffffffffffff") + maxExpArray[79] = NewBig("0x03eab73b3bbfe282243ce1ffffffffffff") + maxExpArray[80] = NewBig("0x03c1771ac9fb6b4c18e229ffffffffffff") + maxExpArray[81] = NewBig("0x0399e96897690418f785257fffffffffff") + maxExpArray[82] = NewBig("0x0373fc456c53bb779bf0ea9fffffffffff") + maxExpArray[83] = NewBig("0x034f9e8e490c48e67e6ab8bfffffffffff") + maxExpArray[84] = NewBig("0x032cbfd4a7adc790560b3337ffffffffff") + maxExpArray[85] = NewBig("0x030b50570f6e5d2acca94613ffffffffff") + maxExpArray[86] = NewBig("0x02eb40f9f620fda6b56c2861ffffffffff") + maxExpArray[87] = NewBig("0x02cc8340ecb0d0f520a6af58ffffffffff") + maxExpArray[88] = NewBig("0x02af09481380a0a35cf1ba02ffffffffff") + maxExpArray[89] = NewBig("0x0292c5bdd3b92ec810287b1b3fffffffff") + maxExpArray[90] = NewBig("0x0277abdcdab07d5a77ac6d6b9fffffffff") + maxExpArray[91] = NewBig("0x025daf6654b1eaa55fd64df5efffffffff") + maxExpArray[92] = NewBig("0x0244c49c648baa98192dce88b7ffffffff") + maxExpArray[93] = NewBig("0x022ce03cd5619a311b2471268bffffffff") + maxExpArray[94] = NewBig("0x0215f77c045fbe885654a44a0fffffffff") + maxExpArray[95] = NewBig("0x01ffffffffffffffffffffffffffffffff") + maxExpArray[96] = NewBig("0x01eaefdbdaaee7421fc4d3ede5ffffffff") + maxExpArray[97] = NewBig("0x01d6bd8b2eb257df7e8ca57b09bfffffff") + maxExpArray[98] = NewBig("0x01c35fedd14b861eb0443f7f133fffffff") + maxExpArray[99] = NewBig("0x01b0ce43b322bcde4a56e8ada5afffffff") + maxExpArray[100] = NewBig("0x019f0028ec1fff007f5a195a39dfffffff") + maxExpArray[101] = NewBig("0x018ded91f0e72ee74f49b15ba527ffffff") + maxExpArray[102] = NewBig("0x017d8ec7f04136f4e5615fd41a63ffffff") + maxExpArray[103] = NewBig("0x016ddc6556cdb84bdc8d12d22e6fffffff") + maxExpArray[104] = NewBig("0x015ecf52776a1155b5bd8395814f7fffff") + maxExpArray[105] = NewBig("0x015060c256cb23b3b3cc3754cf40ffffff") + maxExpArray[106] = NewBig("0x01428a2f98d728ae223ddab715be3fffff") + maxExpArray[107] = NewBig("0x013545598e5c23276ccf0ede68034fffff") + maxExpArray[108] = NewBig("0x01288c4161ce1d6f54b7f61081194fffff") + maxExpArray[109] = NewBig("0x011c592761c666aa641d5a01a40f17ffff") + maxExpArray[110] = NewBig("0x0110a688680a7530515f3e6e6cfdcdffff") + maxExpArray[111] = NewBig("0x01056f1b5bedf75c6bcb2ce8aed428ffff") + maxExpArray[112] = NewBig("0x00faadceceeff8a0890f3875f008277fff") + maxExpArray[113] = NewBig("0x00f05dc6b27edad306388a600f6ba0bfff") + maxExpArray[114] = NewBig("0x00e67a5a25da41063de1495d5b18cdbfff") + maxExpArray[115] = NewBig("0x00dcff115b14eedde6fc3aa5353f2e4fff") + maxExpArray[116] = NewBig("0x00d3e7a3924312399f9aae2e0f868f8fff") + maxExpArray[117] = NewBig("0x00cb2ff529eb71e41582cccd5a1ee26fff") + maxExpArray[118] = NewBig("0x00c2d415c3db974ab32a51840c0b67edff") + maxExpArray[119] = NewBig("0x00bad03e7d883f69ad5b0a186184e06bff") + maxExpArray[120] = NewBig("0x00b320d03b2c343d4829abd6075f0cc5ff") + maxExpArray[121] = NewBig("0x00abc25204e02828d73c6e80bcdb1a95bf") + maxExpArray[122] = NewBig("0x00a4b16f74ee4bb2040a1ec6c15fbbf2df") + maxExpArray[123] = NewBig("0x009deaf736ac1f569deb1b5ae3f36c130f") + maxExpArray[124] = NewBig("0x00976bd9952c7aa957f5937d790ef65037") + maxExpArray[125] = NewBig("0x009131271922eaa6064b73a22d0bd4f2bf") + maxExpArray[126] = NewBig("0x008b380f3558668c46c91c49a2f8e967b9") + maxExpArray[127] = NewBig("0x00857ddf0117efa215952912839f6473e6") +} + +func Power( + _baseN *big.Int, + _baseD *big.Int, + _expN uint, + _expD uint, +) (res *big.Int, precision uint, err error) { + var baseLog *big.Int + var base = new(big.Int).Div(new(big.Int).Mul(_baseN, Fixed1), _baseD) + if base.Cmp(OptLogMaxVal) < 0 { + baseLog = optimalLog(base) + } else { + baseLog = generalLog(base) + } + var baseLogTimesExp = new(big.Int).Div(new(big.Int).Mul(baseLog, big.NewInt(int64(_expN))), big.NewInt(int64(_expD))) + if baseLogTimesExp.Cmp(OptExpMaxVal) < 0 { + return optimalExp(baseLogTimesExp), MaxPrecision, nil + } else { + precision, err = findPositionInMaxExpArray(baseLogTimesExp) + if err != nil { + return nil, precision, err + } + return generalExp(new(big.Int).Rsh(baseLogTimesExp, MaxPrecision-precision), precision), precision, nil + } +} + +/* + function power( + uint256 _baseN, + uint256 _baseD, + uint32 _expN, + uint32 _expD + ) internal view returns (uint256, uint8) { + require(_baseN < MAX_NUM); + + uint256 baseLog; + uint256 base = (_baseN * FIXED_1) / _baseD; + if (base < OPT_LOG_MAX_VAL) { + baseLog = optimalLog(base); + } else { + baseLog = generalLog(base); + } + + uint256 baseLogTimesExp = (baseLog * _expN) / _expD; + if (baseLogTimesExp < OPT_EXP_MAX_VAL) { + return (optimalExp(baseLogTimesExp), MAX_PRECISION); + } else { + uint8 precision = findPositionInMaxExpArray(baseLogTimesExp); + return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision); + } + } +*/ + +func optimalLog(x *big.Int) (res *big.Int) { + res = big.NewInt(0) + + if x.Cmp(NewBig("0xd3094c70f034de4b96ff7d5b6f99fcd8")) >= 0 { + res.Add(res, NewBig("0x40000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0xd3094c70f034de4b96ff7d5b6f99fcd8")) + } + // add 1 / 2^1 + if x.Cmp(NewBig("0xa45af1e1f40c333b3de1db4dd55f29a7")) >= 0 { + res.Add(res, NewBig("0x20000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0xa45af1e1f40c333b3de1db4dd55f29a7")) + } + // add 1 / 2^2 + if x.Cmp(NewBig("0x910b022db7ae67ce76b441c27035c6a1")) >= 0 { + res.Add(res, NewBig("0x10000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x910b022db7ae67ce76b441c27035c6a1")) + } + // add 1 / 2^3 + if x.Cmp(NewBig("0x88415abbe9a76bead8d00cf112e4d4a8")) >= 0 { + res.Add(res, NewBig("0x08000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x88415abbe9a76bead8d00cf112e4d4a8")) + } + // add 1 / 2^4 + if x.Cmp(NewBig("0x84102b00893f64c705e841d5d4064bd3")) >= 0 { + res.Add(res, NewBig("0x04000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x84102b00893f64c705e841d5d4064bd3")) + } + // add 1 / 2^5 + if x.Cmp(NewBig("0x8204055aaef1c8bd5c3259f4822735a2")) >= 0 { + res.Add(res, NewBig("0x02000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x8204055aaef1c8bd5c3259f4822735a2")) + } + // add 1 / 2^6 + if x.Cmp(NewBig("0x810100ab00222d861931c15e39b44e99")) >= 0 { + res.Add(res, NewBig("0x01000000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x810100ab00222d861931c15e39b44e99")) + } + // add 1 / 2^7 + if x.Cmp(NewBig("0x808040155aabbbe9451521693554f733")) >= 0 { + res.Add(res, NewBig("0x00800000000000000000000000000000")) + x = new(big.Int).Div(new(big.Int).Mul(x, Fixed1), NewBig("0x808040155aabbbe9451521693554f733")) + } + // add 1 / 2^8 + + var y = new(big.Int).Sub(x, Fixed1) + var z = new(big.Int).Set(y) + var w = new(big.Int).Div(new(big.Int).Mul(y, y), Fixed1) + + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x100000000000000000000000000000000"), y)), NewBig("0x100000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^01 / 01 - y^02 / 02 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), y)), NewBig("0x200000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^03 / 03 - y^04 / 04 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x099999999999999999999999999999999"), y)), NewBig("0x300000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^05 / 05 - y^06 / 06 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x092492492492492492492492492492492"), y)), NewBig("0x400000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^07 / 07 - y^08 / 08 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x08e38e38e38e38e38e38e38e38e38e38e"), y)), NewBig("0x500000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^09 / 09 - y^10 / 10 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b"), y)), NewBig("0x600000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^11 / 11 - y^12 / 12 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x089d89d89d89d89d89d89d89d89d89d89"), y)), NewBig("0x700000000000000000000000000000000"))) + z = new(big.Int).Div(new(big.Int).Mul(z, w), Fixed1) + // add y^13 / 13 - y^14 / 14 + res = new(big.Int).Add(res, new(big.Int).Div(new(big.Int).Mul(z, new(big.Int).Sub(NewBig("0x088888888888888888888888888888888"), y)), NewBig("0x800000000000000000000000000000000"))) + // add y^15 / 15 - y^16 / 16 + + return res +} + +func optimalExp(x *big.Int) (res *big.Int) { + res = big.NewInt(0) + var y = new(big.Int).Mod(x, NewBig("0x10000000000000000000000000000000")) + var z = new(big.Int).Set(y) + // get the input modulo 2^(-3) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x10e1b3be415a0000"))) + // add y^02 * (20! / 02!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x05a0913f6b1e0000"))) + // add y^03 * (20! / 03!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0168244fdac78000"))) + // add y^04 * (20! / 04!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x004807432bc18000"))) + // add y^05 * (20! / 05!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x000c0135dca04000"))) + // add y^06 * (20! / 06!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0001b707b1cdc000"))) + // add y^07 * (20! / 07!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x000036e0f639b800"))) + // add y^08 * (20! / 08!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x00000618fee9f800"))) + // add y^09 * (20! / 09!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000009c197dcc00"))) + // add y^10 * (20! / 10!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000e30dce400"))) + // add y^11 * (20! / 11!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x000000012ebd1300"))) + // add y^12 * (20! / 12!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000017499f00"))) + // add y^13 * (20! / 13!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000001a9d480"))) + // add y^14 * (20! / 14!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x00000000001c6380"))) + // add y^15 * (20! / 15!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x000000000001c638"))) + // add y^16 * (20! / 16!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000000001ab8"))) + // add y^17 * (20! / 17!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x000000000000017c"))) + // add y^18 * (20! / 18!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000000000014"))) + // add y^19 * (20! / 19!) + z = new(big.Int).Div(new(big.Int).Mul(z, y), Fixed1) + res = new(big.Int).Add(res, new(big.Int).Mul(z, NewBig("0x0000000000000001"))) + // add y^20 * (20! / 20!) + res = new(big.Int).Add(new(big.Int).Add(new(big.Int).Div(res, NewBig("0x21c3677c82b40000")), y), Fixed1) + // divide by 20! and then add y^1 / 1! + y^0 / 0! + + if new(big.Int).And(x, NewBig("0x010000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x1c3d6a24ed82218787d624d3e5eba95f9")), NewBig("0x18ebef9eac820ae8682b9793ac6d1e776")) + } + // multiply by e^2^(-3) + if new(big.Int).And(x, NewBig("0x020000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x18ebef9eac820ae8682b9793ac6d1e778")), NewBig("0x1368b2fc6f9609fe7aceb46aa619baed4")) + } + // multiply by e^2^(-2) + if new(big.Int).And(x, NewBig("0x040000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x1368b2fc6f9609fe7aceb46aa619baed5")), NewBig("0x0bc5ab1b16779be3575bd8f0520a9f21f")) + } + // multiply by e^2^(-1) + if new(big.Int).And(x, NewBig("0x080000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x0bc5ab1b16779be3575bd8f0520a9f21e")), NewBig("0x0454aaa8efe072e7f6ddbab84b40a55c9")) + } + // multiply by e^2^(+0) + if new(big.Int).And(x, NewBig("0x100000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x0454aaa8efe072e7f6ddbab84b40a55c5")), NewBig("0x00960aadc109e7a3bf4578099615711ea")) + } + // multiply by e^2^(+1) + if new(big.Int).And(x, NewBig("0x200000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x00960aadc109e7a3bf4578099615711d7")), NewBig("0x0002bf84208204f5977f9a8cf01fdce3d")) + } + // multiply by e^2^(+2) + if new(big.Int).And(x, NewBig("0x400000000000000000000000000000000")).Cmp(Zero) != 0 { + res = new(big.Int).Div(new(big.Int).Mul(res, NewBig("0x0002bf84208204f5977f9a8cf01fdc307")), NewBig("0x0000003c6ab775dd0b95b4cbee7e65d11")) + } + return res +} + +func generalLog(x *big.Int) (res *big.Int) { + res = big.NewInt(0) + // If x >= 2, then we compute the integer part of log2(x), which is larger than 0. + if x.Cmp(Fixed2) >= 0 { + var count = floorLog2(new(big.Int).Div(x, Fixed1)) + x = new(big.Int).Rsh(x, count) + // now x < 2 + res = new(big.Int).Mul(Fixed1, big.NewInt(int64(count))) + } + // If x > 1, then we compute the fraction part of log2(x), which is larger than 0. + if x.Cmp(Fixed1) > 0 { + for i := MaxPrecision; i > 0; i -= 1 { + x = new(big.Int).Div(new(big.Int).Mul(x, x), Fixed1) + // now 1 < x < 4 + if x.Cmp(Fixed2) >= 0 { + x = new(big.Int).Rsh(x, 1) + // now 1 < x < 2 + res = new(big.Int).Add(res, new(big.Int).Lsh(One, uint(i-1))) + } + } + } + res = new(big.Int).Div(new(big.Int).Mul(res, Ln2Numerator), Ln2Denominator) + return res +} + +func floorLog2(_n *big.Int) (res uint) { + res = 0 + if res < 256 { + for _n.Cmp(One) > 0 { + _n = new(big.Int).Rsh(_n, 1) + res += 1 + } + } else { + for s := uint(128); s > 0; s >>= 1 { + if _n.Cmp(new(big.Int).Lsh(One, s)) >= 0 { + _n = new(big.Int).Rsh(_n, s) + res = res | s + } + } + } + return res +} + +func findPositionInMaxExpArray(_x *big.Int) (uint, error) { + var lo = MinPrecision + var hi = MaxPrecision + for lo+1 < hi { + var mid = (lo + hi) / 2 + if maxExpArray[mid].Cmp(_x) >= 0 { + lo = mid + } else { + hi = mid + } + } + if maxExpArray[hi].Cmp(_x) >= 0 { + return hi, nil + } + if maxExpArray[lo].Cmp(_x) >= 0 { + return lo, nil + } + + return 0, errors.New("revert") +} + +func generalExp(_x *big.Int, _precision uint) (res *big.Int) { + var xi = new(big.Int).Set(_x) + res = big.NewInt(0) + + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x3442c4e6074a82f1797f72ac0000000"))) + // add x^02 * (33! / 02!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x116b96f757c380fb287fd0e40000000"))) + // add x^03 * (33! / 03!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x045ae5bdd5f0e03eca1ff4390000000"))) + // add x^04 * (33! / 04!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00defabf91302cd95b9ffda50000000"))) + // add x^05 * (33! / 05!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x002529ca9832b22439efff9b8000000"))) + // add x^06 * (33! / 06!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00054f1cf12bd04e516b6da88000000"))) + // add x^07 * (33! / 07!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000a9e39e257a09ca2d6db51000000"))) + // add x^08 * (33! / 08!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000012e066e7b839fa050c309000000"))) + // add x^09 * (33! / 09!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000001e33d7d926c329a1ad1a800000"))) + // add x^10 * (33! / 10!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000002bee513bdb4a6b19b5f800000"))) + // add x^11 * (33! / 11!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000003a9316fa79b88eccf2a00000"))) + // add x^12 * (33! / 12!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000048177ebe1fa812375200000"))) + // add x^13 * (33! / 13!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000005263fe90242dcbacf00000"))) + // add x^14 * (33! / 14!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000000000057e22099c030d94100000"))) + // add x^15 * (33! / 15!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000057e22099c030d9410000"))) + // add x^16 * (33! / 16!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000052b6b54569976310000"))) + // add x^17 * (33! / 17!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000004985f67696bf748000"))) + // add x^18 * (33! / 18!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000000000000003dea12ea99e498000"))) + // add x^19 * (33! / 19!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000000031880f2214b6e000"))) + // add x^20 * (33! / 20!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000000000000000025bcff56eb36000"))) + // add x^21 * (33! / 21!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000000000000000001b722e10ab1000"))) + // add x^22 * (33! / 22!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000001317c70077000"))) + // add x^23 * (33! / 23!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000000000000cba84aafa00"))) + // add x^24 * (33! / 24!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000000000000082573a0a00"))) + // add x^25 * (33! / 25!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000000000000005035ad900"))) + // add x^26 * (33! / 26!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x000000000000000000000002f881b00"))) + // add x^27 * (33! / 27!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000000000001b29340"))) + // add x^28 * (33! / 28!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x00000000000000000000000000efc40"))) + // add x^29 * (33! / 29!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000000000000007fe0"))) + // add x^30 * (33! / 30!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000000000000000420"))) + // add x^31 * (33! / 31!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000000000000000021"))) + // add x^32 * (33! / 32!) + xi = new(big.Int).Rsh(new(big.Int).Mul(xi, _x), _precision) + res = new(big.Int).Add(res, new(big.Int).Mul(xi, NewBig("0x0000000000000000000000000000001"))) + // add x^33 * (33! / 33!) + res = new(big.Int).Add(new(big.Int).Add(new(big.Int).Div(res, NewBig("0x688589cc0e9505e2f2fee5580000000")), _x), new(big.Int).Lsh(One, _precision)) + // divide by 33! and then add x^1 / 1! + x^0 / 0! + + return res +} diff --git a/pkg/source/crowdswapv2/math.go b/pkg/source/crowdswapv2/math.go new file mode 100644 index 000000000..09385156e --- /dev/null +++ b/pkg/source/crowdswapv2/math.go @@ -0,0 +1,34 @@ +package uniswap + +import ( + "math/big" +) + +func NewBig10(s string) (res *big.Int) { + res, _ = new(big.Int).SetString(s, 10) + return res +} + +func getAmountOut( + amountIn *big.Int, + reserveIn *big.Int, + reserveOut *big.Int, + tokenWeightIn uint, + tokenWeightOut uint, + swapFee *big.Int, +) (res *big.Int, err error) { + var amountInWithFee = new(big.Int).Mul(amountIn, new(big.Int).Sub(bOne, swapFee)) + if tokenWeightIn == tokenWeightOut { + res = new(big.Int).Div(new(big.Int).Mul(reserveOut, amountInWithFee), new(big.Int).Add(new(big.Int).Mul(reserveIn, bOne), amountInWithFee)) + return res, nil + } + var baseN = new(big.Int).Add(new(big.Int).Mul(reserveIn, bOne), amountInWithFee) + res, precision, err := Power(baseN, new(big.Int).Mul(reserveIn, bOne), tokenWeightIn, tokenWeightOut) + if err != nil { + return nil, err + } + var temp1 = new(big.Int).Mul(reserveOut, res) + var temp2 = new(big.Int).Lsh(reserveOut, precision) + res = new(big.Int).Div(new(big.Int).Sub(temp1, temp2), res) + return res, nil +} diff --git a/pkg/source/crowdswapv2/pool_simulator.go b/pkg/source/crowdswapv2/pool_simulator.go new file mode 100644 index 000000000..ff5f1d8db --- /dev/null +++ b/pkg/source/crowdswapv2/pool_simulator.go @@ -0,0 +1,127 @@ +package uniswap + +import ( + "fmt" + "math/big" + "strings" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" +) + +type PoolSimulator struct { + pool.Pool + Weights []uint + gas Gas +} + +func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { + swapFeeFl := new(big.Float).Mul(big.NewFloat(entityPool.SwapFee), bOneFloat) + swapFee, _ := swapFeeFl.Int(nil) + tokens := make([]string, 2) + weights := make([]uint, 2) + reserves := make([]*big.Int, 2) + if len(entityPool.Reserves) == 2 && len(entityPool.Tokens) == 2 { + var weight0 = uint(50) + if entityPool.Tokens[0].Weight > 0 { + weight0 = entityPool.Tokens[0].Weight + } + var weight1 = uint(50) + if entityPool.Tokens[1].Weight > 0 { + weight1 = entityPool.Tokens[1].Weight + } + tokens[0] = entityPool.Tokens[0].Address + weights[0] = weight0 + reserves[0] = NewBig10(entityPool.Reserves[0]) + tokens[1] = entityPool.Tokens[1].Address + weights[1] = weight1 + reserves[1] = NewBig10(entityPool.Reserves[1]) + } + info := pool.PoolInfo{ + Address: strings.ToLower(entityPool.Address), + ReserveUsd: entityPool.ReserveUsd, + SwapFee: swapFee, + Exchange: entityPool.Exchange, + Type: entityPool.Type, + Tokens: tokens, + Reserves: reserves, + Checked: false, + } + + return &PoolSimulator{ + Pool: pool.Pool{Info: info}, + Weights: weights, + gas: defaultGas, + }, nil +} + +func (t *PoolSimulator) CalcAmountOut( + tokenAmountIn pool.TokenAmount, + tokenOut string, +) (*pool.CalcAmountOutResult, error) { + var tokenInIndex = t.GetTokenIndex(tokenAmountIn.Token) + var tokenOutIndex = t.GetTokenIndex(tokenOut) + + if tokenInIndex < 0 || tokenOutIndex < 0 { + return &pool.CalcAmountOutResult{}, fmt.Errorf("tokenInIndex: %v or tokenOutIndex: %v is not correct", tokenInIndex, tokenOutIndex) + } + + amountOut, err := getAmountOut( + tokenAmountIn.Amount, + t.Info.Reserves[tokenInIndex], + t.Info.Reserves[tokenOutIndex], + t.Weights[tokenInIndex], + t.Weights[tokenOutIndex], + t.Info.SwapFee, + ) + if err != nil { + return &pool.CalcAmountOutResult{}, err + } + + var totalGas = t.gas.SwapBase + if t.Weights[tokenInIndex] != t.Weights[tokenOutIndex] { + totalGas = t.gas.SwapNonBase + } + + if amountOut.Cmp(zeroBI) > 0 { + return &pool.CalcAmountOutResult{ + TokenAmountOut: &pool.TokenAmount{ + Token: tokenOut, + Amount: amountOut, + }, + Fee: &pool.TokenAmount{ + Token: tokenAmountIn.Token, + Amount: nil, + }, + Gas: totalGas, + }, nil + } + + return &pool.CalcAmountOutResult{}, fmt.Errorf("invalid amount out: %v", amountOut.String()) +} + +func (t *PoolSimulator) UpdateBalance(params pool.UpdateBalanceParams) { + input, output := params.TokenAmountIn, params.TokenAmountOut + var inputAmount = new(big.Int).Div(new(big.Int).Mul(input.Amount, new(big.Int).Sub(bOne, t.Info.SwapFee)), bOne) + var outputAmount = output.Amount + for i := range t.Info.Tokens { + if t.Info.Tokens[i] == input.Token { + t.Info.Reserves[i] = new(big.Int).Add(t.Info.Reserves[i], inputAmount) + } + if t.Info.Tokens[i] == output.Token { + t.Info.Reserves[i] = new(big.Int).Sub(t.Info.Reserves[i], outputAmount) + } + } +} + +func (t *PoolSimulator) GetMetaInfo(_ string, _ string) interface{} { + if t.GetInfo().SwapFee == nil { + return Meta{ + SwapFee: defaultSwapFee, + } + } + + return Meta{ + SwapFee: t.GetInfo().SwapFee.String(), + } +} diff --git a/pkg/source/crowdswapv2/pool_tracker.go b/pkg/source/crowdswapv2/pool_tracker.go new file mode 100644 index 000000000..422af0608 --- /dev/null +++ b/pkg/source/crowdswapv2/pool_tracker.go @@ -0,0 +1,55 @@ +package uniswap + +import ( + "context" + "time" + + "github.com/KyberNetwork/ethrpc" + "github.com/KyberNetwork/logger" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" +) + +type PoolTracker struct { + ethrpcClient *ethrpc.Client +} + +func NewPoolTracker( + ethrpcClient *ethrpc.Client, +) (*PoolTracker, error) { + return &PoolTracker{ + ethrpcClient: ethrpcClient, + }, nil +} + +func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entity.Pool, error) { + logger.Infof("[Uniswap V2] Start getting new state of pool: %v", p.Address) + + rpcRequest := d.ethrpcClient.NewRequest() + rpcRequest.SetContext(ctx) + + var reserves Reserves + + rpcRequest.AddCall(ðrpc.Call{ + ABI: uniswapV2PairABI, + Target: p.Address, + Method: pairMethodGetReserves, + Params: nil, + }, []interface{}{&reserves}) + + _, err := rpcRequest.Call() + if err != nil { + logger.Errorf("failed to process tryAggregate for pool: %v, err: %v", p.Address, err) + return entity.Pool{}, err + } + + p.Timestamp = time.Now().Unix() + p.Reserves = entity.PoolReserves{ + reserves.Reserve0.String(), + reserves.Reserve1.String(), + } + + logger.Infof("[Uniswap V2] Finish getting new state of pool: %v", p.Address) + + return p, nil +} diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go new file mode 100644 index 000000000..d112e5cb9 --- /dev/null +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -0,0 +1,183 @@ +package uniswap + +import ( + "context" + "encoding/json" + "math/big" + "strings" + "time" + + "github.com/KyberNetwork/ethrpc" + "github.com/KyberNetwork/logger" + "github.com/ethereum/go-ethereum/common" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util" +) + +type PoolsListUpdater struct { + config *Config + ethrpcClient *ethrpc.Client +} + +func NewPoolsListUpdater( + cfg *Config, + ethrpcClient *ethrpc.Client, +) *PoolsListUpdater { + return &PoolsListUpdater{ + config: cfg, + ethrpcClient: ethrpcClient, + } +} + +func (d *PoolsListUpdater) InitPool(_ context.Context) error { + return nil +} + +func (d *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte) ([]entity.Pool, []byte, error) { + var metadata Metadata + if len(metadataBytes) != 0 { + err := json.Unmarshal(metadataBytes, &metadata) + if err != nil { + return nil, metadataBytes, err + } + } + + // Add timestamp to the context so that each run iteration will have something different + ctx = util.NewContextWithTimestamp(ctx) + + var lengthBI *big.Int + + getNumPoolsRequest := d.ethrpcClient.NewRequest() + getNumPoolsRequest.AddCall(ðrpc.Call{ + ABI: uniswapV2FactoryABI, + Target: d.config.FactoryAddress, + Method: factoryMethodAllPairsLength, + Params: nil, + }, []interface{}{&lengthBI}) + + if _, err := getNumPoolsRequest.Call(); err != nil { + logger.Errorf("failed to get number of pairs from factory, err: %v", err) + return nil, metadataBytes, err + } + + totalNumberOfPools := int(lengthBI.Int64()) + + currentOffset := metadata.Offset + batchSize := d.config.NewPoolLimit + if currentOffset+batchSize > totalNumberOfPools { + batchSize = totalNumberOfPools - currentOffset + if batchSize <= 0 { + return nil, metadataBytes, nil + } + } + + getPairAddressRequest := d.ethrpcClient.NewRequest() + + var pairAddresses = make([]common.Address, batchSize) + for j := 0; j < batchSize; j++ { + getPairAddressRequest.AddCall(ðrpc.Call{ + ABI: uniswapV2FactoryABI, + Target: d.config.FactoryAddress, + Method: factoryMethodGetPair, + Params: []interface{}{big.NewInt(int64(currentOffset + j))}, + }, []interface{}{&pairAddresses[j]}) + } + resp, err := getPairAddressRequest.TryAggregate() + if err != nil { + logger.Errorf("failed to process aggregate, err: %v", err) + return nil, metadataBytes, err + } + + var successPairAddresses []common.Address + for i, isSuccess := range resp.Result { + if isSuccess { + successPairAddresses = append(successPairAddresses, pairAddresses[i]) + } + } + + pools, err := d.processBatch(ctx, successPairAddresses) + if err != nil { + logger.Errorf("failed to process update new pool, err: %v", err) + return nil, metadataBytes, err + } + + nextOffset := currentOffset + batchSize + newMetadataBytes, err := json.Marshal(Metadata{ + Offset: nextOffset, + }) + if err != nil { + return nil, metadataBytes, err + } + + if len(pools) > 0 { + logger.Infof("scan UniswapV2Factory with batch size %v, progress: %d/%d", batchSize, currentOffset+batchSize, totalNumberOfPools) + } + + return pools, newMetadataBytes, nil +} + +func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []common.Address) ([]entity.Pool, error) { + var limit = len(pairAddresses) + var token0Addresses = make([]common.Address, limit) + var token1Addresses = make([]common.Address, limit) + + rpcRequest := d.ethrpcClient.NewRequest() + rpcRequest.SetContext(ctx) + + for i := 0; i < limit; i++ { + rpcRequest.AddCall(ðrpc.Call{ + ABI: uniswapV2PairABI, + Target: pairAddresses[i].Hex(), + Method: pairMethodToken0, + Params: nil, + }, []interface{}{&token0Addresses[i]}) + + rpcRequest.AddCall(ðrpc.Call{ + ABI: uniswapV2PairABI, + Target: pairAddresses[i].Hex(), + Method: pairMethodToken1, + Params: nil, + }, []interface{}{&token1Addresses[i]}) + } + + if _, err := rpcRequest.Aggregate(); err != nil { + logger.Errorf("failed to process aggregate to get 2 tokens from pair contract, err: %v", err) + return nil, err + } + + pools := make([]entity.Pool, 0, len(pairAddresses)) + + for i, pairAddress := range pairAddresses { + p := strings.ToLower(pairAddress.Hex()) + token0Address := strings.ToLower(token0Addresses[i].Hex()) + token1Address := strings.ToLower(token1Addresses[i].Hex()) + + var token0 = entity.PoolToken{ + Address: token0Address, + Weight: defaultTokenWeight, + Swappable: true, + } + var token1 = entity.PoolToken{ + Address: token1Address, + Weight: defaultTokenWeight, + Swappable: true, + } + + var newPool = entity.Pool{ + Address: p, + ReserveUsd: 0, + AmplifiedTvl: 0, + SwapFee: d.config.SwapFee, + Exchange: d.config.DexID, + Type: DexTypeUniswap, + Timestamp: time.Now().Unix(), + Reserves: []string{reserveZero, reserveZero}, + Tokens: []*entity.PoolToken{&token0, &token1}, + } + + pools = append(pools, newPool) + } + + return pools, nil +} diff --git a/pkg/source/crowdswapv2/type.go b/pkg/source/crowdswapv2/type.go new file mode 100644 index 000000000..67002509c --- /dev/null +++ b/pkg/source/crowdswapv2/type.go @@ -0,0 +1,24 @@ +package uniswap + +import ( + "math/big" +) + +type Reserves struct { + Reserve0 *big.Int + Reserve1 *big.Int + BlockTimestampLast uint32 +} + +type Metadata struct { + Offset int `json:"offset"` +} + +type Gas struct { + SwapBase int64 + SwapNonBase int64 +} + +type Meta struct { + SwapFee string `json:"swapFee"` +} From 426568284d0bd8912ac794f62b551a045b7a5c97 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 11:22:49 +0200 Subject: [PATCH 02/17] rename abi files --- .../abis/{UniswapV2Factory.json => CrowdswapV2Factory.json} | 0 .../crowdswapv2/abis/{UniswapV2Pair.json => CrowdswapV2Pair.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pkg/source/crowdswapv2/abis/{UniswapV2Factory.json => CrowdswapV2Factory.json} (100%) rename pkg/source/crowdswapv2/abis/{UniswapV2Pair.json => CrowdswapV2Pair.json} (100%) diff --git a/pkg/source/crowdswapv2/abis/UniswapV2Factory.json b/pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json similarity index 100% rename from pkg/source/crowdswapv2/abis/UniswapV2Factory.json rename to pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json diff --git a/pkg/source/crowdswapv2/abis/UniswapV2Pair.json b/pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json similarity index 100% rename from pkg/source/crowdswapv2/abis/UniswapV2Pair.json rename to pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json From 4dc9409202cfd8ad1a131982a304624a3e8f38b2 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 11:29:21 +0200 Subject: [PATCH 03/17] insert ABI's --- .../crowdswapv2/abis/CrowdswapV2Factory.json | 312 ++++++++++++++++-- .../crowdswapv2/abis/CrowdswapV2Pair.json | 176 ++++++---- 2 files changed, 411 insertions(+), 77 deletions(-) diff --git a/pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json b/pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json index a2f132767..7976569b4 100644 --- a/pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json +++ b/pkg/source/crowdswapv2/abis/CrowdswapV2Factory.json @@ -1,15 +1,67 @@ [ { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "_feeToSetter", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" }, { "anonymous": false, @@ -43,7 +95,19 @@ "type": "event" }, { - "constant": true, + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { "inputs": [ { "internalType": "uint256", @@ -59,12 +123,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "allPairsLength", "outputs": [ @@ -74,12 +136,17 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [ { "internalType": "address", @@ -100,12 +167,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], "name": "feeTo", "outputs": [ @@ -115,12 +180,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "feeToSetter", "outputs": [ @@ -130,12 +193,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -156,12 +217,98 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + }, + { + "internalType": "uint8", + "name": "_swapFee", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_platformFee", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "platformFee", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [ { "internalType": "address", @@ -171,12 +318,10 @@ ], "name": "setFeeTo", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -186,8 +331,133 @@ ], "name": "setFeeToSetter", "outputs": [], - "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenB", + "type": "address" + }, + { + "internalType": "uint8", + "name": "_swapFee", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_platformFee", + "type": "uint8" + } + ], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_router", + "type": "address" + } + ], + "name": "setRouter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapFee", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenB", + "type": "address" + }, + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bool", + "name": "_isVerified", + "type": "bool" + } + ], + "name": "verify", + "outputs": [], "stateMutability": "nonpayable", "type": "function" } -] +] \ No newline at end of file diff --git a/pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json b/pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json index 53582c1ed..7f9ae2721 100644 --- a/pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json +++ b/pkg/source/crowdswapv2/abis/CrowdswapV2Pair.json @@ -1,7 +1,6 @@ [ { "inputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "constructor" }, @@ -61,6 +60,25 @@ "name": "Burn", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "swapFee", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "platformFee", + "type": "uint8" + } + ], + "name": "FeeSet", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -174,7 +192,25 @@ "type": "event" }, { - "constant": true, + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isVerified", + "type": "bool" + } + ], + "name": "VerifiedListUpdated", + "type": "event" + }, + { "inputs": [], "name": "DOMAIN_SEPARATOR", "outputs": [ @@ -184,12 +220,10 @@ "type": "bytes32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MINIMUM_LIQUIDITY", "outputs": [ @@ -199,12 +233,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "PERMIT_TYPEHASH", "outputs": [ @@ -214,12 +246,10 @@ "type": "bytes32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -240,12 +270,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -266,12 +294,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -287,12 +313,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -313,12 +337,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], "name": "decimals", "outputs": [ @@ -328,12 +350,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "factory", "outputs": [ @@ -343,12 +363,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "getReserves", "outputs": [ @@ -368,12 +386,10 @@ "type": "uint32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -388,12 +404,29 @@ ], "name": "initialize", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isVerified", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "kLast", "outputs": [ @@ -403,12 +436,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -424,12 +455,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], "name": "name", "outputs": [ @@ -439,12 +468,10 @@ "type": "string" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -460,12 +487,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -505,12 +530,23 @@ ], "name": "permit", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "platformFee", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "price0CumulativeLast", "outputs": [ @@ -520,12 +556,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "price1CumulativeLast", "outputs": [ @@ -535,12 +569,28 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, + "inputs": [ + { + "internalType": "uint8", + "name": "_swapFee", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_platformFee", + "type": "uint8" + } + ], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [ { "internalType": "address", @@ -550,12 +600,10 @@ ], "name": "skim", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "uint256", @@ -580,12 +628,23 @@ ], "name": "swap", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "swapFee", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "symbol", "outputs": [ @@ -595,21 +654,17 @@ "type": "string" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [], "name": "sync", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], "name": "token0", "outputs": [ @@ -619,12 +674,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "token1", "outputs": [ @@ -634,12 +687,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ @@ -649,12 +700,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -675,12 +724,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -706,8 +753,25 @@ "type": "bool" } ], - "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bool", + "name": "_isVerified", + "type": "bool" + } + ], + "name": "verify", + "outputs": [], "stateMutability": "nonpayable", "type": "function" } -] +] \ No newline at end of file From 77e2906b1b2da024deae3146b166c8bdfa8a1a1e Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 12:31:25 +0200 Subject: [PATCH 04/17] updating types & packages --- pkg/source/crowdswapv2/abis.go | 10 +++++----- pkg/source/crowdswapv2/config.go | 2 +- pkg/source/crowdswapv2/constant.go | 4 ++-- pkg/source/crowdswapv2/embed.go | 6 +++--- pkg/source/crowdswapv2/formula.go | 2 +- pkg/source/crowdswapv2/math.go | 2 +- pkg/source/crowdswapv2/pool_simulator.go | 2 +- pkg/source/crowdswapv2/pool_tracker.go | 8 ++++---- pkg/source/crowdswapv2/pools_list_updater.go | 14 +++++++------- pkg/source/crowdswapv2/type.go | 2 +- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/pkg/source/crowdswapv2/abis.go b/pkg/source/crowdswapv2/abis.go index 61da017f1..6260333d3 100644 --- a/pkg/source/crowdswapv2/abis.go +++ b/pkg/source/crowdswapv2/abis.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "bytes" @@ -7,8 +7,8 @@ import ( ) var ( - uniswapV2PairABI abi.ABI - uniswapV2FactoryABI abi.ABI + crowdswapV2PairABI abi.ABI + crowdswapV2FactoryABI abi.ABI ) func init() { @@ -17,10 +17,10 @@ func init() { data []byte }{ { - &uniswapV2PairABI, pairABIJson, + &crowdswapV2PairABI, pairABIJson, }, { - &uniswapV2FactoryABI, factoryABIJson, + &crowdswapV2FactoryABI, factoryABIJson, }, } diff --git a/pkg/source/crowdswapv2/config.go b/pkg/source/crowdswapv2/config.go index 76d8df051..a35b7a808 100644 --- a/pkg/source/crowdswapv2/config.go +++ b/pkg/source/crowdswapv2/config.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 type Config struct { DexID string `json:"dexID"` diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index fb2f27ebb..18b0fc6af 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -1,9 +1,9 @@ -package uniswap +package crowdswapv2 import "math/big" const ( - DexTypeUniswap = "uniswap" + DexTypeCrowdswapV2 = "crowdswapv2" defaultTokenWeight = 50 reserveZero = "0" ) diff --git a/pkg/source/crowdswapv2/embed.go b/pkg/source/crowdswapv2/embed.go index 85dfd525c..856a97c7e 100644 --- a/pkg/source/crowdswapv2/embed.go +++ b/pkg/source/crowdswapv2/embed.go @@ -1,9 +1,9 @@ -package uniswap +package crowdswapv2 import _ "embed" -//go:embed abis/UniswapV2Pair.json +//go:embed abis/CrowdswapV2Pair.json var pairABIJson []byte -//go:embed abis/UniswapV2Factory.json +//go:embed abis/CrowdswapV2Factory.json var factoryABIJson []byte diff --git a/pkg/source/crowdswapv2/formula.go b/pkg/source/crowdswapv2/formula.go index f1cb7fdc7..a59d77c06 100644 --- a/pkg/source/crowdswapv2/formula.go +++ b/pkg/source/crowdswapv2/formula.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "errors" diff --git a/pkg/source/crowdswapv2/math.go b/pkg/source/crowdswapv2/math.go index 09385156e..6c0064233 100644 --- a/pkg/source/crowdswapv2/math.go +++ b/pkg/source/crowdswapv2/math.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "math/big" diff --git a/pkg/source/crowdswapv2/pool_simulator.go b/pkg/source/crowdswapv2/pool_simulator.go index ff5f1d8db..9271ff5e2 100644 --- a/pkg/source/crowdswapv2/pool_simulator.go +++ b/pkg/source/crowdswapv2/pool_simulator.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "fmt" diff --git a/pkg/source/crowdswapv2/pool_tracker.go b/pkg/source/crowdswapv2/pool_tracker.go index 422af0608..882a32d53 100644 --- a/pkg/source/crowdswapv2/pool_tracker.go +++ b/pkg/source/crowdswapv2/pool_tracker.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "context" @@ -23,7 +23,7 @@ func NewPoolTracker( } func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entity.Pool, error) { - logger.Infof("[Uniswap V2] Start getting new state of pool: %v", p.Address) + logger.Infof("[Crowdswap V2] Start getting new state of pool: %v", p.Address) rpcRequest := d.ethrpcClient.NewRequest() rpcRequest.SetContext(ctx) @@ -31,7 +31,7 @@ func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entit var reserves Reserves rpcRequest.AddCall(ðrpc.Call{ - ABI: uniswapV2PairABI, + ABI: crowdswapV2PairABI, Target: p.Address, Method: pairMethodGetReserves, Params: nil, @@ -49,7 +49,7 @@ func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entit reserves.Reserve1.String(), } - logger.Infof("[Uniswap V2] Finish getting new state of pool: %v", p.Address) + logger.Infof("[Crowdswap V2] Finish getting new state of pool: %v", p.Address) return p, nil } diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index d112e5cb9..f5352c4dd 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "context" @@ -50,7 +50,7 @@ func (d *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte getNumPoolsRequest := d.ethrpcClient.NewRequest() getNumPoolsRequest.AddCall(ðrpc.Call{ - ABI: uniswapV2FactoryABI, + ABI: crowdswapV2FactoryABI, Target: d.config.FactoryAddress, Method: factoryMethodAllPairsLength, Params: nil, @@ -77,7 +77,7 @@ func (d *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte var pairAddresses = make([]common.Address, batchSize) for j := 0; j < batchSize; j++ { getPairAddressRequest.AddCall(ðrpc.Call{ - ABI: uniswapV2FactoryABI, + ABI: crowdswapV2FactoryABI, Target: d.config.FactoryAddress, Method: factoryMethodGetPair, Params: []interface{}{big.NewInt(int64(currentOffset + j))}, @@ -111,7 +111,7 @@ func (d *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte } if len(pools) > 0 { - logger.Infof("scan UniswapV2Factory with batch size %v, progress: %d/%d", batchSize, currentOffset+batchSize, totalNumberOfPools) + logger.Infof("scan CrowdswapV2Factory with batch size %v, progress: %d/%d", batchSize, currentOffset+batchSize, totalNumberOfPools) } return pools, newMetadataBytes, nil @@ -127,14 +127,14 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com for i := 0; i < limit; i++ { rpcRequest.AddCall(ðrpc.Call{ - ABI: uniswapV2PairABI, + ABI: crowdswapV2PairABI, Target: pairAddresses[i].Hex(), Method: pairMethodToken0, Params: nil, }, []interface{}{&token0Addresses[i]}) rpcRequest.AddCall(ðrpc.Call{ - ABI: uniswapV2PairABI, + ABI: crowdswapV2PairABI, Target: pairAddresses[i].Hex(), Method: pairMethodToken1, Params: nil, @@ -170,7 +170,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com AmplifiedTvl: 0, SwapFee: d.config.SwapFee, Exchange: d.config.DexID, - Type: DexTypeUniswap, + Type: DexTypeCrowdswapV2, Timestamp: time.Now().Unix(), Reserves: []string{reserveZero, reserveZero}, Tokens: []*entity.PoolToken{&token0, &token1}, diff --git a/pkg/source/crowdswapv2/type.go b/pkg/source/crowdswapv2/type.go index 67002509c..aabea02d1 100644 --- a/pkg/source/crowdswapv2/type.go +++ b/pkg/source/crowdswapv2/type.go @@ -1,4 +1,4 @@ -package uniswap +package crowdswapv2 import ( "math/big" From 48480338965d2b9533a29333c8a20d928559bf6d Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 14:49:43 +0200 Subject: [PATCH 05/17] crowdswap: add to handler --- pkg/source/handler.go | 12 ++++++++++++ pkg/util/abi/method_test.go | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/pkg/source/handler.go b/pkg/source/handler.go index e69ae84a5..141feb7bf 100644 --- a/pkg/source/handler.go +++ b/pkg/source/handler.go @@ -9,6 +9,7 @@ import ( balancerComposableStable "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/balancer-composable-stable" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/biswap" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/camelot" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/crowdswapv2" //TODO crowdswap "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/dmm" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/dodo" @@ -63,6 +64,15 @@ func NewPoolsListUpdaterHandler( cfg.DexID = scanDexCfg.Id return uniswapv3.NewPoolsListUpdater(&cfg), nil + case crowdswapv2.DexTypeCrowdswapV2: + var cfg crowdswapv2.Config + err := PropertiesToStruct(scanDexCfg.Properties, &cfg) + if err != nil { + return nil, err + } + cfg.DexID = scanDexCfg.Id + + return crowdswapv2.NewPoolsListUpdater(&cfg, ethrpcClient), nil case dmm.DexTypeDMM: var cfg dmm.Config err := PropertiesToStruct(scanDexCfg.Properties, &cfg) @@ -355,6 +365,8 @@ func NewPoolTrackerHandler( cfg.DexID = scanDexCfg.Id return uniswapv3.NewPoolTracker(&cfg, ethrpcClient) + case crowdswapv2.DexTypeCrowdswapV2: + return crowdswapv2.NewPoolTracker(ethrpcClient) case dmm.DexTypeDMM: return dmm.NewPoolTracker(ethrpcClient) case elastic.DexTypeElastic: diff --git a/pkg/util/abi/method_test.go b/pkg/util/abi/method_test.go index 3a0197713..17733b4b1 100644 --- a/pkg/util/abi/method_test.go +++ b/pkg/util/abi/method_test.go @@ -19,6 +19,11 @@ func TestGenMethodID(t *testing.T) { types: []string{"uint256", "bytes", "uint256"}, expectedId: "0xd0796174", }, + { + rawName: "executeCrowdSwapV2", + types: []string{"uint256", "bytes", "uint256"}, + expectedId: "0xd0796174", + }, { rawName: "executeStableSwap", types: []string{"uint256", "bytes", "uint256"}, From c56615d4334ee75cb16067a986e641f18455a341 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 21:53:43 +0200 Subject: [PATCH 06/17] getting fee --- pkg/source/crowdswapv2/constant.go | 3 +- pkg/source/crowdswapv2/pool_tracker.go | 42 ++++++++++++++++---- pkg/source/crowdswapv2/pools_list_updater.go | 21 +++++++--- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index 18b0fc6af..8d1c0f915 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -3,7 +3,7 @@ package crowdswapv2 import "math/big" const ( - DexTypeCrowdswapV2 = "crowdswapv2" + DexTypeCrowdswapV2 = "crowdswapv2" defaultTokenWeight = 50 reserveZero = "0" ) @@ -13,6 +13,7 @@ const ( factoryMethodAllPairsLength = "allPairsLength" pairMethodToken0 = "token0" pairMethodToken1 = "token1" + pairMethodGetSwapFee = "swapFee" pairMethodGetReserves = "getReserves" ) diff --git a/pkg/source/crowdswapv2/pool_tracker.go b/pkg/source/crowdswapv2/pool_tracker.go index 882a32d53..faff48c9f 100644 --- a/pkg/source/crowdswapv2/pool_tracker.go +++ b/pkg/source/crowdswapv2/pool_tracker.go @@ -25,31 +25,59 @@ func NewPoolTracker( func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entity.Pool, error) { logger.Infof("[Crowdswap V2] Start getting new state of pool: %v", p.Address) - rpcRequest := d.ethrpcClient.NewRequest() - rpcRequest.SetContext(ctx) + var ( + reserves Reserves + swapFee uint8 + ) - var reserves Reserves + calls := d.ethrpcClient.NewRequest().SetContext(ctx) - rpcRequest.AddCall(ðrpc.Call{ + calls.AddCall(ðrpc.Call{ ABI: crowdswapV2PairABI, Target: p.Address, Method: pairMethodGetReserves, Params: nil, }, []interface{}{&reserves}) - _, err := rpcRequest.Call() + calls.AddCall(ðrpc.Call{ + ABI: crowdswapV2PairABI, + Target: p.Address, + Method: pairMethodGetSwapFee, + Params: nil, + }, []interface{}{&swapFee}) + + resp, err := calls.TryAggregate() if err != nil { - logger.Errorf("failed to process tryAggregate for pool: %v, err: %v", p.Address, err) + logger.WithFields(logger.Fields{ + "poolAddress": p.Address, + "error": err, + }).Errorf("[Crowdswap V2]: failed to process tryAggregate for pool") + return entity.Pool{}, err + } + + if len(resp.Result) != 2 { + logger.WithFields(logger.Fields{ + "error": err, + }).Errorf("[Crowdswap V2]: result of tryAggregate for pool: %v is broken", p.Address) + return entity.Pool{}, err + } + + if !resp.Result[0] || !resp.Result[1] { + logger.Warnf("[Crowdswap V2]: failed to fetch pool state, reserves: %v, swapFee: %v", resp.Result[0], resp.Result[1]) return entity.Pool{}, err } + var swapFeeFL float64 = float64(swapFee) / 1000 + p.SwapFee = swapFeeFL p.Timestamp = time.Now().Unix() p.Reserves = entity.PoolReserves{ reserves.Reserve0.String(), reserves.Reserve1.String(), } - logger.Infof("[Crowdswap V2] Finish getting new state of pool: %v", p.Address) + logger.WithFields(logger.Fields{ + "poolAddress": p.Address, + }).Infof("[Crowdswap V2] Finish getting new state of pool") return p, nil } diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index f5352c4dd..b90448642 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -121,27 +121,35 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com var limit = len(pairAddresses) var token0Addresses = make([]common.Address, limit) var token1Addresses = make([]common.Address, limit) + var swapFees = make([]int8, limit) - rpcRequest := d.ethrpcClient.NewRequest() - rpcRequest.SetContext(ctx) + calls := d.ethrpcClient.NewRequest().SetContext(ctx) for i := 0; i < limit; i++ { - rpcRequest.AddCall(ðrpc.Call{ + calls.AddCall(ðrpc.Call{ ABI: crowdswapV2PairABI, Target: pairAddresses[i].Hex(), Method: pairMethodToken0, Params: nil, }, []interface{}{&token0Addresses[i]}) - rpcRequest.AddCall(ðrpc.Call{ + calls.AddCall(ðrpc.Call{ ABI: crowdswapV2PairABI, Target: pairAddresses[i].Hex(), Method: pairMethodToken1, Params: nil, }, []interface{}{&token1Addresses[i]}) + + calls.AddCall(ðrpc.Call{ + ABI: crowdswapV2PairABI, + Target: pairAddresses[i].Hex(), + Method: pairMethodGetSwapFee, + Params: nil, + }, []interface{}{&swapFees[i]}) + } - if _, err := rpcRequest.Aggregate(); err != nil { + if _, err := calls.Aggregate(); err != nil { logger.Errorf("failed to process aggregate to get 2 tokens from pair contract, err: %v", err) return nil, err } @@ -163,12 +171,13 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Weight: defaultTokenWeight, Swappable: true, } + var swapFeeFL float64 = float64(swapFees[i]) / 1000 var newPool = entity.Pool{ Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - SwapFee: d.config.SwapFee, + SwapFee: swapFeeFL, Exchange: d.config.DexID, Type: DexTypeCrowdswapV2, Timestamp: time.Now().Unix(), From fa91e13a008bd1cb9bcee3fba4c6589c6f37276b Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 21:55:31 +0200 Subject: [PATCH 07/17] Add question --- pkg/source/crowdswapv2/pools_list_updater.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index b90448642..7e74c35d6 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -177,7 +177,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - SwapFee: swapFeeFL, + SwapFee: swapFeeFL, //FIXME: can we use d.config.SwapFee? Exchange: d.config.DexID, Type: DexTypeCrowdswapV2, Timestamp: time.Now().Unix(), From bb1c85e26293abb1a14117e20f7dd5b7f206deac Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 21:58:00 +0200 Subject: [PATCH 08/17] add question --- pkg/source/crowdswapv2/pools_list_updater.go | 2 +- pkg/source/handler.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index 7e74c35d6..a5f8b92e3 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -177,7 +177,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - SwapFee: swapFeeFL, //FIXME: can we use d.config.SwapFee? + SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? Exchange: d.config.DexID, Type: DexTypeCrowdswapV2, Timestamp: time.Now().Unix(), diff --git a/pkg/source/handler.go b/pkg/source/handler.go index 141feb7bf..2d7bcd868 100644 --- a/pkg/source/handler.go +++ b/pkg/source/handler.go @@ -9,7 +9,7 @@ import ( balancerComposableStable "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/balancer-composable-stable" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/biswap" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/camelot" - "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/crowdswapv2" //TODO crowdswap + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/crowdswapv2" //FIXME: crowdswap: Should we do anything? "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/curve" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/dmm" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/dodo" From 3a6d7a721b396a878d4e71ff1b755c8a10614477 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 22:25:30 +0200 Subject: [PATCH 09/17] add read me --- pkg/source/crowdswapv2/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 pkg/source/crowdswapv2/README.md diff --git a/pkg/source/crowdswapv2/README.md b/pkg/source/crowdswapv2/README.md new file mode 100644 index 000000000..ef0d2ee31 --- /dev/null +++ b/pkg/source/crowdswapv2/README.md @@ -0,0 +1 @@ +# Crowdswap From 84c54b5eb390b89e5e87a780ad42b8a3eea27814 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 31 Jul 2023 22:28:46 +0200 Subject: [PATCH 10/17] remove readme --- pkg/source/crowdswapv2/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 pkg/source/crowdswapv2/README.md diff --git a/pkg/source/crowdswapv2/README.md b/pkg/source/crowdswapv2/README.md deleted file mode 100644 index ef0d2ee31..000000000 --- a/pkg/source/crowdswapv2/README.md +++ /dev/null @@ -1 +0,0 @@ -# Crowdswap From 8030e713569913463a43bdcf640491973f8ce825 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Tue, 8 Aug 2023 16:09:47 +0200 Subject: [PATCH 11/17] CrowdswapV2: UnitTest --- pkg/source/crowdswapv2/constant.go | 9 +- pkg/source/crowdswapv2/pool_simulator.go | 10 +- pkg/source/crowdswapv2/pool_simulator_test.go | 106 ++++++++++++++++++ pkg/source/crowdswapv2/pools_list_updater.go | 8 +- 4 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 pkg/source/crowdswapv2/pool_simulator_test.go diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index 8d1c0f915..f5874fb54 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -18,9 +18,8 @@ const ( ) var ( - zeroBI = big.NewInt(0) - defaultGas = Gas{SwapBase: 60000, SwapNonBase: 102000} - defaultSwapFee = "2" - bOne = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) - bOneFloat, _ = new(big.Float).SetString("1000000000000000000") + zeroBI = big.NewInt(0) + defaultGas = Gas{SwapBase: 60000, SwapNonBase: 102000} + bOne = new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil) + oneFloat float64 = 10 ) diff --git a/pkg/source/crowdswapv2/pool_simulator.go b/pkg/source/crowdswapv2/pool_simulator.go index 9271ff5e2..59725ff22 100644 --- a/pkg/source/crowdswapv2/pool_simulator.go +++ b/pkg/source/crowdswapv2/pool_simulator.go @@ -16,8 +16,8 @@ type PoolSimulator struct { } func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { - swapFeeFl := new(big.Float).Mul(big.NewFloat(entityPool.SwapFee), bOneFloat) - swapFee, _ := swapFeeFl.Int(nil) + //for 0.3% fee, the swapFee in the real pair should be set to 3 + swapFee := big.NewInt(int64(entityPool.SwapFee * oneFloat)) tokens := make([]string, 2) weights := make([]uint, 2) reserves := make([]*big.Int, 2) @@ -36,6 +36,8 @@ func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { tokens[1] = entityPool.Tokens[1].Address weights[1] = weight1 reserves[1] = NewBig10(entityPool.Reserves[1]) + } else { + return nil, fmt.Errorf("number of reserves: %v or number of tokens: %v is not correct", len(entityPool.Reserves), len(entityPool.Tokens)) } info := pool.PoolInfo{ Address: strings.ToLower(entityPool.Address), @@ -116,9 +118,7 @@ func (t *PoolSimulator) UpdateBalance(params pool.UpdateBalanceParams) { func (t *PoolSimulator) GetMetaInfo(_ string, _ string) interface{} { if t.GetInfo().SwapFee == nil { - return Meta{ - SwapFee: defaultSwapFee, - } + return nil } return Meta{ diff --git a/pkg/source/crowdswapv2/pool_simulator_test.go b/pkg/source/crowdswapv2/pool_simulator_test.go new file mode 100644 index 000000000..0b27a9ec7 --- /dev/null +++ b/pkg/source/crowdswapv2/pool_simulator_test.go @@ -0,0 +1,106 @@ +package crowdswapv2 + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + poolPkg "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" + utils "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" +) + +func TestGetAmountOut(t *testing.T) { + poolAddress := "0x1788f8dec1c2054d653f8330eedcdf3dfbeb42ac" + token0Address := "0x2aa69e007c32cf6637511353b89dce0b473851a9" + token1Address := "0x5aea5775959fbc2557cc8789bc1bf90a239d9a91" + + testCases := []struct { + name string + entityPool entity.Pool + tokenAmountIn poolPkg.TokenAmount + tokenOut string + swapFee *big.Int + expectedAmountOut *poolPkg.TokenAmount + expectedErr error + }{ + { + name: "test token0 as tokenIn", + entityPool: entity.Pool{ + Address: poolAddress, + SwapFee: 0.3, //% + Exchange: "crowdswapv2", + Type: "v2", + Reserves: []string{ + "38819698878426432914729", + "46113879614283", + }, + Tokens: []*entity.PoolToken{ + { + Address: token0Address, + Swappable: true, + }, + { + Address: token1Address, + Swappable: true, + }, + }, + }, + tokenAmountIn: poolPkg.TokenAmount{ + Token: token0Address, + Amount: utils.NewBig("100000000000000000000"), + }, + tokenOut: token1Address, + expectedAmountOut: &poolPkg.TokenAmount{ + Token: token1Address, + Amount: utils.NewBig("118130133815"), + }, + expectedErr: nil, + }, + { + name: "test token1 as tokenIn", + entityPool: entity.Pool{ + Address: poolAddress, + SwapFee: 0.3, //% + Exchange: "crowdswapv2", + Type: "v2", + Reserves: []string{ + "38819698878426432914729", + "46113879614283", + }, + Tokens: []*entity.PoolToken{ + { + Address: token0Address, + Swappable: true, + }, + { + Address: token1Address, + Swappable: true, + }, + }, + }, + tokenAmountIn: poolPkg.TokenAmount{ + Token: token1Address, + Amount: utils.NewBig("10000000000000"), + }, + tokenOut: token0Address, + expectedAmountOut: &poolPkg.TokenAmount{ + Token: token0Address, + Amount: utils.NewBig("6900956219144033296901"), + }, + expectedErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + pool, err := NewPoolSimulator(tc.entityPool) + assert.Nil(t, err) + calcAmountOutResult, err := pool.CalcAmountOut(tc.tokenAmountIn, tc.tokenOut) + + assert.Equal(t, tc.expectedErr, err) + assert.Equal(t, tc.expectedAmountOut, calcAmountOutResult.TokenAmountOut) + }) + } +} diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index a5f8b92e3..44581756e 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -30,10 +30,6 @@ func NewPoolsListUpdater( } } -func (d *PoolsListUpdater) InitPool(_ context.Context) error { - return nil -} - func (d *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte) ([]entity.Pool, []byte, error) { var metadata Metadata if len(metadataBytes) != 0 { @@ -121,7 +117,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com var limit = len(pairAddresses) var token0Addresses = make([]common.Address, limit) var token1Addresses = make([]common.Address, limit) - var swapFees = make([]int8, limit) + var swapFees = make([]uint8, limit) calls := d.ethrpcClient.NewRequest().SetContext(ctx) @@ -177,7 +173,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? + SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? We use for example 3 in our pair to refer 0.3% fee Exchange: d.config.DexID, Type: DexTypeCrowdswapV2, Timestamp: time.Now().Unix(), From 0f2be907ad56f9d434bd78de02839874835d6f08 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Tue, 8 Aug 2023 19:30:08 +0200 Subject: [PATCH 12/17] CrowdswapV2: bps in config --- pkg/source/crowdswapv2/constant.go | 2 ++ pkg/source/crowdswapv2/pool_tracker.go | 4 ++-- pkg/source/crowdswapv2/pools_list_updater.go | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index f5874fb54..950a6f2c6 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -6,6 +6,8 @@ const ( DexTypeCrowdswapV2 = "crowdswapv2" defaultTokenWeight = 50 reserveZero = "0" + + bps = 1000 ) const ( diff --git a/pkg/source/crowdswapv2/pool_tracker.go b/pkg/source/crowdswapv2/pool_tracker.go index faff48c9f..1b3e588ee 100644 --- a/pkg/source/crowdswapv2/pool_tracker.go +++ b/pkg/source/crowdswapv2/pool_tracker.go @@ -51,7 +51,7 @@ func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entit logger.WithFields(logger.Fields{ "poolAddress": p.Address, "error": err, - }).Errorf("[Crowdswap V2]: failed to process tryAggregate for pool") + }).Errorf("[Crowdswap V2]: failed to process tryAggregate for pool: %v, err: %v", p.Address, err) return entity.Pool{}, err } @@ -67,7 +67,7 @@ func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entit return entity.Pool{}, err } - var swapFeeFL float64 = float64(swapFee) / 1000 + var swapFeeFL float64 = float64(swapFee) / bps p.SwapFee = swapFeeFL p.Timestamp = time.Now().Unix() p.Reserves = entity.PoolReserves{ diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index 44581756e..68355f106 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -167,7 +167,7 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Weight: defaultTokenWeight, Swappable: true, } - var swapFeeFL float64 = float64(swapFees[i]) / 1000 + var swapFeeFL float64 = float64(swapFees[i]) / bps var newPool = entity.Pool{ Address: p, From 80328f67294e25d1d670508c9b5e2673d921d5fb Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Fri, 11 Aug 2023 08:15:48 +0200 Subject: [PATCH 13/17] CrowdswapV2: Update swap fee calculation --- pkg/source/crowdswapv2/pool_tracker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/source/crowdswapv2/pool_tracker.go b/pkg/source/crowdswapv2/pool_tracker.go index 1b3e588ee..9b17571fd 100644 --- a/pkg/source/crowdswapv2/pool_tracker.go +++ b/pkg/source/crowdswapv2/pool_tracker.go @@ -67,7 +67,7 @@ func (d *PoolTracker) GetNewPoolState(ctx context.Context, p entity.Pool) (entit return entity.Pool{}, err } - var swapFeeFL float64 = float64(swapFee) / bps + var swapFeeFL float64 = float64(swapFee) p.SwapFee = swapFeeFL p.Timestamp = time.Now().Unix() p.Reserves = entity.PoolReserves{ From dcdb66e7d79fd615ab8de265904c0cfb42411e97 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Fri, 11 Aug 2023 09:18:32 +0200 Subject: [PATCH 14/17] CrowdswapV2: Delete swapFee from pools_list_updater --- pkg/source/crowdswapv2/pools_list_updater.go | 21 ++++++-------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index 68355f106..70199e249 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -117,7 +117,6 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com var limit = len(pairAddresses) var token0Addresses = make([]common.Address, limit) var token1Addresses = make([]common.Address, limit) - var swapFees = make([]uint8, limit) calls := d.ethrpcClient.NewRequest().SetContext(ctx) @@ -136,13 +135,6 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Params: nil, }, []interface{}{&token1Addresses[i]}) - calls.AddCall(ðrpc.Call{ - ABI: crowdswapV2PairABI, - Target: pairAddresses[i].Hex(), - Method: pairMethodGetSwapFee, - Params: nil, - }, []interface{}{&swapFees[i]}) - } if _, err := calls.Aggregate(); err != nil { @@ -167,18 +159,17 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Weight: defaultTokenWeight, Swappable: true, } - var swapFeeFL float64 = float64(swapFees[i]) / bps var newPool = entity.Pool{ Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? We use for example 3 in our pair to refer 0.3% fee - Exchange: d.config.DexID, - Type: DexTypeCrowdswapV2, - Timestamp: time.Now().Unix(), - Reserves: []string{reserveZero, reserveZero}, - Tokens: []*entity.PoolToken{&token0, &token1}, + // SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? We use for example 3 in our pair to refer 0.3% fee + Exchange: d.config.DexID, + Type: DexTypeCrowdswapV2, + Timestamp: time.Now().Unix(), + Reserves: []string{reserveZero, reserveZero}, + Tokens: []*entity.PoolToken{&token0, &token1}, } pools = append(pools, newPool) From f62b49265923adffe509c89e27cece0952a8b7d2 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Fri, 11 Aug 2023 21:39:05 +0200 Subject: [PATCH 15/17] crowdswapV2: Correcting swap fee for test --- pkg/source/crowdswapv2/constant.go | 9 ++++----- pkg/source/crowdswapv2/pool_simulator.go | 3 +-- pkg/source/crowdswapv2/pool_simulator_test.go | 4 ++-- pkg/source/crowdswapv2/pools_list_updater.go | 11 +++++------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index 950a6f2c6..368ef5a62 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -3,7 +3,7 @@ package crowdswapv2 import "math/big" const ( - DexTypeCrowdswapV2 = "crowdswapv2" + DexTypeCrowdswapV2 = "crowdswap-v2" defaultTokenWeight = 50 reserveZero = "0" @@ -20,8 +20,7 @@ const ( ) var ( - zeroBI = big.NewInt(0) - defaultGas = Gas{SwapBase: 60000, SwapNonBase: 102000} - bOne = new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil) - oneFloat float64 = 10 + zeroBI = big.NewInt(0) + defaultGas = Gas{SwapBase: 60000, SwapNonBase: 102000} + bOne = new(big.Int).Exp(big.NewInt(10), big.NewInt(3), nil) ) diff --git a/pkg/source/crowdswapv2/pool_simulator.go b/pkg/source/crowdswapv2/pool_simulator.go index 59725ff22..eb9c853d1 100644 --- a/pkg/source/crowdswapv2/pool_simulator.go +++ b/pkg/source/crowdswapv2/pool_simulator.go @@ -16,8 +16,7 @@ type PoolSimulator struct { } func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { - //for 0.3% fee, the swapFee in the real pair should be set to 3 - swapFee := big.NewInt(int64(entityPool.SwapFee * oneFloat)) + swapFee := big.NewInt(int64(entityPool.SwapFee)) tokens := make([]string, 2) weights := make([]uint, 2) reserves := make([]*big.Int, 2) diff --git a/pkg/source/crowdswapv2/pool_simulator_test.go b/pkg/source/crowdswapv2/pool_simulator_test.go index 0b27a9ec7..9ca63d5ee 100644 --- a/pkg/source/crowdswapv2/pool_simulator_test.go +++ b/pkg/source/crowdswapv2/pool_simulator_test.go @@ -29,7 +29,7 @@ func TestGetAmountOut(t *testing.T) { name: "test token0 as tokenIn", entityPool: entity.Pool{ Address: poolAddress, - SwapFee: 0.3, //% + SwapFee: 3, Exchange: "crowdswapv2", Type: "v2", Reserves: []string{ @@ -62,7 +62,7 @@ func TestGetAmountOut(t *testing.T) { name: "test token1 as tokenIn", entityPool: entity.Pool{ Address: poolAddress, - SwapFee: 0.3, //% + SwapFee: 3, Exchange: "crowdswapv2", Type: "v2", Reserves: []string{ diff --git a/pkg/source/crowdswapv2/pools_list_updater.go b/pkg/source/crowdswapv2/pools_list_updater.go index 70199e249..ece273bc2 100644 --- a/pkg/source/crowdswapv2/pools_list_updater.go +++ b/pkg/source/crowdswapv2/pools_list_updater.go @@ -164,12 +164,11 @@ func (d *PoolsListUpdater) processBatch(ctx context.Context, pairAddresses []com Address: p, ReserveUsd: 0, AmplifiedTvl: 0, - // SwapFee: swapFeeFL, //FIXME: crowdswap can we use d.config.SwapFee? We use for example 3 in our pair to refer 0.3% fee - Exchange: d.config.DexID, - Type: DexTypeCrowdswapV2, - Timestamp: time.Now().Unix(), - Reserves: []string{reserveZero, reserveZero}, - Tokens: []*entity.PoolToken{&token0, &token1}, + Exchange: d.config.DexID, + Type: DexTypeCrowdswapV2, + Timestamp: time.Now().Unix(), + Reserves: []string{reserveZero, reserveZero}, + Tokens: []*entity.PoolToken{&token0, &token1}, } pools = append(pools, newPool) From d3ae7deda54e5f899678a8b19745d7c75f7a02e5 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Mon, 21 Aug 2023 12:23:31 +0200 Subject: [PATCH 16/17] Crowdswap: Remove unused parameter bps --- pkg/source/crowdswapv2/constant.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/source/crowdswapv2/constant.go b/pkg/source/crowdswapv2/constant.go index 368ef5a62..6c75eda55 100644 --- a/pkg/source/crowdswapv2/constant.go +++ b/pkg/source/crowdswapv2/constant.go @@ -6,8 +6,6 @@ const ( DexTypeCrowdswapV2 = "crowdswap-v2" defaultTokenWeight = 50 reserveZero = "0" - - bps = 1000 ) const ( From eb64415bb6593465dd3b216cf4d68b754e0d46b4 Mon Sep 17 00:00:00 2001 From: Nader Aryabarzan Date: Wed, 23 Aug 2023 10:32:02 +0200 Subject: [PATCH 17/17] CrowSwapV2: fixing method test --- pkg/util/abi/method_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/abi/method_test.go b/pkg/util/abi/method_test.go index 17733b4b1..e68d8374f 100644 --- a/pkg/util/abi/method_test.go +++ b/pkg/util/abi/method_test.go @@ -22,7 +22,7 @@ func TestGenMethodID(t *testing.T) { { rawName: "executeCrowdSwapV2", types: []string{"uint256", "bytes", "uint256"}, - expectedId: "0xd0796174", + expectedId: "0xbeac25ac", }, { rawName: "executeStableSwap",