Commit 5860be39 authored by luxq's avatar luxq

update

parent 34b01480
......@@ -23,19 +23,11 @@ cd pancakeswaper
make
```
#### 2. fill in the `accounts.json` file with the accounts you want to do swap for.
The example of the `accounts.json` file is as follow:
```json
[
{
"address": "0x",
"private": "0x"
},
{
"address": "0x",
"private": "0x"
}
]
#### 2. fill in the `accounts.csv` file with the accounts you want to do swap for.
The example of the `accounts.csv` file is as follow:
```csv
useraddress, privatekey, recipient
0xeFbb75e446Ec2d8493B3d4d91aC3118953f69b55, 0x1111111111111111, 0xc437593d9C296bf9A5002522A86dad8a4d4Af808
```
#### 4. change configure
......@@ -55,6 +47,12 @@ param:
# tx deadline, unit is minutes, set 0 to disable.
deadline: 20
pair:
# pair address.
pair: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a"
# klko address
token: "0x215324115417a13879f865Dc5BB651B18A781a59"
rpc:
env: "bsc"
pool: 20
......@@ -62,7 +60,7 @@ rpc:
log:
level: "debug"
users: "accounts.json"
users: "accounts.csv"
```
#### 5. run the program
......
useraddress, privatekey, recipient
0xeFbb75e446Ec2d8493B3d4d91aC3118953f69b55, 0x1111111111111111, 0xc437593d9C296bf9A5002522A86dad8a4d4Af808
\ No newline at end of file
[
{"address":"","private":"0x"},
{"address":"","private":"0x"},
{"address":"","private":"0x"}
]
\ No newline at end of file
......@@ -12,6 +12,12 @@ param:
# tx deadline, unit is minutes, set 0 to disable.
deadline: 20
pair:
# pair address.
pair: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a"
# klko address
token: "0x215324115417a13879f865Dc5BB651B18A781a59"
rpc:
env: "bsc"
pool: 20
......@@ -19,4 +25,4 @@ rpc:
log:
level: "debug"
users: "accounts.json"
\ No newline at end of file
users: "accounts.csv"
\ No newline at end of file
......@@ -12,6 +12,7 @@ import (
type Config struct {
Log LogConfig `yaml:"log"`
Param ParamConfig `yaml:"param"`
Pair PairConfig `yaml:"pair"`
Rpc RpcConfig `yaml:"rpc"`
Users string `yaml:"users"`
}
......@@ -25,6 +26,11 @@ type ParamConfig struct {
Deadline int64 `yaml:"deadline"`
}
type PairConfig struct {
Pair string `yaml:"pair"`
Token string `yaml:"token"`
}
type RpcConfig struct {
Env string `yaml:"env"`
PoolSize int `yaml:"pool"`
......
package pancake
import (
"code.wuban.net.cn/service/pancakeswapper/config"
"code.wuban.net.cn/service/pancakeswapper/contracts/buildparam"
"code.wuban.net.cn/service/pancakeswapper/contracts/v3pool"
"code.wuban.net.cn/service/pancakeswapper/types"
......@@ -30,7 +31,7 @@ func leftPadding(data []byte, length int) []byte {
return append(padding, data...)
}
func MakeV3SwapExactInPathData(env types.Env) []byte {
func MakeV3SwapExactInPathData(env types.Env, cfg *config.Config) []byte {
//0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3
//0000000000000000000000000000000000000000000000001bc16d674ec80000
//0000000000000000000000000000000000000000000000002620b5d4cdab6c04
......@@ -40,7 +41,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte {
//55d398326f99059ff775485246999027b3197955002710215324115417a13879f865dc5bb651b18a781a59000000000000000000000000000000000000000000
token0 := common.HexToAddress(env.USDT)
token1 := common.HexToAddress(env.KLKO)
token1 := common.HexToAddress(cfg.Pair.Token)
fee := big.NewInt(10000)
data := make([]byte, 0)
data = append(data, token0.Bytes()...)
......@@ -49,7 +50,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte {
return data
}
func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn) ([]byte, error) {
func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn, cfg *config.Config) ([]byte, error) {
//0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3
//0000000000000000000000000000000000000000000000000de0b6b3a7640000
//00000000000000000000000000000000000000000000000012d0ee4f5819f972
......@@ -59,7 +60,7 @@ func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn) ([]byte, err
//55d398326f99059ff775485246999027b3197955002710215324115417a13879
//f865dc5bb651b18a781a59000000000000000000000000000000000000000000
param.Path = MakeV3SwapExactInPathData(env)
param.Path = MakeV3SwapExactInPathData(env, cfg)
buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI))
data, err := buildAbi.Pack("buildParamV3_SWAP_EXACT_IN", param.Recipient, param.AmountIn, param.AmountOutMin, param.Path, param.PayerIsUser)
......@@ -103,10 +104,10 @@ func MakePermit2PermitData(acc *types.Account, env types.Env) ([]byte, error) {
// amountIn is the amount of input token (USDT) to swap.
// slippage is the maximum slippage allowed for the swap, the value is percent mul 1000, eg: 20 is 2%.
// feeRate is the fee charged by the pool, the value is percent mul 1000000, eg: 10000 is 1%.
func GetAmountOutMin(client *ethclient.Client, env types.Env, amountIn *big.Int,
func GetAmountOutMin(cfg *config.Config, client *ethclient.Client, env types.Env, amountIn *big.Int,
slippage int64, feeRate *big.Int) (*big.Int, error) {
// get slot0 data.
pool := common.HexToAddress(env.Pool)
pool := common.HexToAddress(cfg.Pair.Pair)
contract, err := v3pool.NewV3Pool(pool, client)
if err != nil {
return nil, err
......@@ -216,6 +217,7 @@ func MakePermit2PermitData2(acc *types.Account, env types.Env, client *ethclient
// Pack the data
buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI))
// todo: check method name.
data, err := buildAbi.Pack("buildParamPermit2", permitSingle, signature)
if err != nil {
return nil, err
......
......@@ -26,7 +26,7 @@ func (s *Swapper) Run() {
work.WorkInit(env.ChainId)
// 1. read account info from json file
accs := work.LoadAccounts(s.cfg.Users)
accs := work.LoadAccountsFromCsv(s.cfg.Users)
work.SetTotalUser(len(accs))
waitCh := make(chan struct{})
......
......@@ -15,6 +15,7 @@ type Account struct {
//Nonce uint64 `json:"-"`
PK *ecdsa.PrivateKey `json:"-"`
Addr common.Address `json:"-"`
Recipient string `json:“recipient"`
}
func (a *Account) sign(chainid *big.Int, tx *types.Transaction) (*types.Transaction, error) {
......
......@@ -6,14 +6,11 @@ var (
func init() {
allEnv["bsc"] = Env{
//RPC: "https://bscnode.bitheart.org",
RPC: "https://four.rpc.48.club",
USDT: "0x55d398326f99059ff775485246999027b3197955",
KLKO: "0x215324115417a13879f865Dc5BB651B18A781a59", // KLKO
Permit2: "0x31c2F6fcFf4F8759b3Bd5Bf0e1084A055615c768",
Router: "0x1b81D678ffb9C0263b24A97847620C99d213eB14",
//Router: "0x1A0A18AC4BECDDbd6389559687d1A73d8927E416",
Pool: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a",
UniversalRouter: "0x1A0A18AC4BECDDbd6389559687d1A73d8927E416",
ChainId: 56,
}
}
......@@ -21,10 +18,11 @@ func init() {
type Env struct {
RPC string
USDT string
KLKO string
//KLKO string
Permit2 string
Router string
Pool string
Router string // v3 router.
UniversalRouter string
//Pool string
ChainId int64
}
......
......@@ -9,6 +9,7 @@ import (
"code.wuban.net.cn/service/pancakeswapper/pancake"
"code.wuban.net.cn/service/pancakeswapper/types"
"context"
"encoding/csv"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi"
......@@ -17,6 +18,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
log "github.com/sirupsen/logrus"
"math/big"
"os"
"strings"
......@@ -25,6 +27,8 @@ import (
var (
failedHistory = make(chan *types.Account, 1000000)
dec = new(big.Int).SetUint64(1000000000000000000)
fee = big.NewInt(10000)
)
func LoadAccounts(file string) []*types.Account {
......@@ -39,6 +43,48 @@ func LoadAccounts(file string) []*types.Account {
}
return accs
}
func LoadAccountsFromCsv(filepath string) []*types.Account {
// parse csv file, column is address, private key, recipient.
file, err := os.Open(filepath)
if err != nil {
panic(fmt.Errorf("Error opening file:", err))
}
defer file.Close()
// Create a CSV reader
reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
panic(fmt.Errorf("Error reading CSV file:", err))
}
var parsedRecords []*types.Account
for i, record := range records {
// Ensure the record has the expected number of columns
if len(record) != 3 {
log.Errorf("Skipping malformed record at row %d: %+v\n", i, record)
continue
}
if i == 0 && !strings.HasPrefix(record[0], "0x") {
log.Warningf("Skipping malformed record at row %d: %+v\n", i, record)
// skip title line.
continue
}
// Map the fields to the Record struct
parsedRecord := &types.Account{
Address: strings.TrimSpace(record[0]),
PrivateKey: strings.TrimSpace(record[1]),
Recipient: strings.TrimSpace(record[2]),
}
parsedRecords = append(parsedRecords, parsedRecord)
}
log.WithField("records", len(parsedRecords)).Info("Successfully loaded accounts from csv file")
return parsedRecords
}
func addTofailed(acc *types.Account) {
IncrFailedUser()
failedHistory <- acc
......@@ -58,17 +104,18 @@ func waitTx(client *ethclient.Client, tx *ethtypes.Transaction) *ethtypes.Receip
}
}
func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env) error {
func accountApproveWithPermit(client *ethclient.Client, acc *types.Account, env types.Env) error {
cfg := config.Global
//permit2 := common.HexToAddress(env.Permit2)
permit2 := common.HexToAddress(env.Permit2)
usdt, err := erc20.NewTokenContract(common.HexToAddress(env.USDT), client)
if err != nil {
return fmt.Errorf("erc20.NewTokenContract failed: %v", err)
}
//router, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client)
//if err != nil {
// return fmt.Errorf("build param contract failed: %v", err)
//}
// router need set to Universal Router.
router, err := buildparam.NewParamContract(common.HexToAddress(env.UniversalRouter), client)
if err != nil {
return fmt.Errorf("build param contract failed: %v", err)
}
txopts := &bind.TransactOpts{
From: acc.Addr,
......@@ -78,54 +125,93 @@ func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env)
addNewTx := func(tx *ethtypes.Transaction) {
waitTx(client, tx)
}
//if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
// return fmt.Errorf("usdt approve permit2 failed: %v", err)
//} else {
// addNewTx(tx)
//}
// first approve usdt to permit2.
//if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
if tx, err := usdt.Approve(txopts, common.HexToAddress(env.Router), abi.MaxUint256); err != nil {
return fmt.Errorf("usdt approve pool failed: %v", err)
allow, err := usdt.Allowance(&bind.CallOpts{
From: acc.Addr,
BlockNumber: nil,
Context: context.Background(),
}, acc.Addr, permit2)
if allow.Int64() == 0 {
if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
return fmt.Errorf("usdt approve permit2 failed: %v", err)
} else {
addNewTx(tx)
}
}
//permitData, err := pancake.MakePermit2PermitData2(acc, env, client)
//if err != nil {
// return fmt.Errorf("make permit data: %v", err)
//}
//
//inputs := make([][]byte, 0)
//inputs = append(inputs, permitData)
permitData, err := pancake.MakePermit2PermitData2(acc, env, client)
if err != nil {
return fmt.Errorf("make permit data: %v", err)
}
//deadline := time.Now().Unix() + cfg.Param.Deadline*60
inputs := make([][]byte, 0)
inputs = append(inputs, permitData)
//if execTx, err := router.Execute(txopts, []byte{byte(pancake.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline)); err != nil {
// return fmt.Errorf("execute permit2 permit failed: %v", err)
//} else {
// addNewTx(execTx)
//}
// set permit with universal router execute.
deadline := time.Now().Unix() + cfg.Param.Deadline*60
if execTx, err := router.Execute(txopts, []byte{byte(pancake.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline)); err != nil {
return fmt.Errorf("execute permit2 permit failed: %v", err)
} else {
addNewTx(execTx)
}
return nil
}
func HandlerAccountApprove(acc *types.Account, env types.Env, idx uint) {
func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env) error {
cfg := config.Global
// 1. approve usdt token to permit2.
// 2. call permit2 to approve usdt token.
permit2 := common.HexToAddress(env.Permit2)
client := clientpool.GetClient()
usdt, err := erc20.NewTokenContract(common.HexToAddress(env.USDT), client)
if err != nil {
return fmt.Errorf("erc20.NewTokenContract failed: %v", err)
}
txopts := &bind.TransactOpts{
From: acc.Addr,
Signer: acc.SignTx,
GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)),
}
addNewTx := func(tx *ethtypes.Transaction) {
waitTx(client, tx)
}
allow, _ := usdt.Allowance(&bind.CallOpts{
From: acc.Addr,
BlockNumber: nil,
Context: context.Background(),
}, acc.Addr, common.HexToAddress(env.Router))
if allow.Int64() == 0 {
if tx, err := usdt.Approve(txopts, common.HexToAddress(env.Router), abi.MaxUint256); err != nil {
return fmt.Errorf("usdt approve pool failed: %v", err)
} else {
addNewTx(tx)
}
}
return nil
}
func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
cfg := config.Global
client := clientpool.GetClient()
pkstr := acc.PrivateKey
if strings.HasPrefix(pkstr, "0x") || strings.HasPrefix(pkstr, "0X") {
pkstr = acc.PrivateKey[2:]
}
var err error
acc.PK, err = crypto.HexToECDSA(pkstr)
if err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to create usdt contract: %v", acc.Address, err))
WriteLog(fmt.Sprintf("[%s] failed: invalid private hex string: %v", acc.Address, pkstr))
return
}
router, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client)
if err != nil {
acc.Addr = crypto.PubkeyToAddress(acc.PK.PublicKey)
if strings.ToLower(acc.Addr.Hex()) != strings.ToLower(acc.Address) {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to create router contract: %v", acc.Address, err))
WriteLog(fmt.Sprintf("[%s] failed: given address not match with private key (%s), please check", acc.Address, acc.Addr))
return
}
if err := accountApprove(client, acc, env); err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] do approve failed: %v", acc.Address, err))
return
}
......@@ -136,45 +222,63 @@ func HandlerAccountApprove(acc *types.Account, env types.Env, idx uint) {
}
addNewTx := func(tx *ethtypes.Transaction) {
IncrTotalTx()
waitTx(client, tx)
receipt := waitTx(client, tx)
for _, log := range receipt.Logs {
if log.Topics[0] == pancake.TransferTopic {
token, _ := erc20.NewTokenContract(common.HexToAddress(cfg.Pair.Token), client)
event, _ := token.ParseTransfer(*log)
if event.To == acc.Addr {
val, _ := new(big.Float).SetInt(event.Value).Float64()
val = val / 1e18
WriteLog(fmt.Sprintf("[%s] receive %f token", acc.Address, val))
IncrReceiveToken(val)
}
if event.From == acc.Addr {
val, _ := new(big.Float).SetInt(event.Value).Float64()
val = val / 1e18
IncrCostToken(val)
}
}
}
IncrFinishedTx()
}
// first approve usdt to permit2.
if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed approve usdt to permit2 nft contract: %v", acc.Address, err))
return
} else {
addNewTx(tx)
}
for i := 0; i < cfg.Param.Count; i++ {
in := new(big.Int).Mul(big.NewInt(cfg.Param.Volume), dec)
in = new(big.Int).Div(in, big.NewInt(10)) // param volume 1 is 0.1
v3r, err := v3router.NewV3Router(common.HexToAddress(env.Router), client)
permitData, err := pancake.MakePermit2PermitData(acc, env)
// calc amountOutMin with price and slippage.
amountOutMin, err := pancake.GetAmountOutMin(cfg, client, env, in, cfg.Param.Slippage, fee)
if err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to make permit data: %v", acc.Address, err))
WriteLog(fmt.Sprintf("[%s] failed: failed to get amount out min: %v", acc.Address, err))
return
}
inputs := make([][]byte, 0)
inputs = append(inputs, permitData)
deadline := time.Now().Unix() + cfg.Param.Deadline*60
if execTx, err := router.Execute(txopts, []byte{byte(pancake.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline)); err != nil {
if execTx, err := v3r.ExactInputSingle(txopts, v3router.ISwapRouterExactInputSingleParams{
TokenIn: common.HexToAddress(env.USDT),
TokenOut: common.HexToAddress(cfg.Pair.Token),
Recipient: common.HexToAddress(acc.Recipient),
AmountIn: in,
AmountOutMinimum: amountOutMin,
Deadline: big.NewInt(deadline),
Fee: fee,
SqrtPriceLimitX96: big.NewInt(0),
}); err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed execute permit2 permit: %v", acc.Address, err))
WriteLog(fmt.Sprintf("[%s] failed: failed execute swap: %v", acc.Address, err))
return
} else {
addNewTx(execTx)
}
WriteLog(fmt.Sprintf("[%s] finish: have no more times to mint", acc.Address))
}
WriteLog(fmt.Sprintf("[%s] finish: have finished all swap", acc.Address))
IncrFinishedUser()
return
}
func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
func HandlerAccountSwapWithUniversalRouter(acc *types.Account, env types.Env, idx uint) {
cfg := config.Global
client := clientpool.GetClient()
pkstr := acc.PrivateKey
......@@ -190,35 +294,38 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
return
}
acc.Addr = crypto.PubkeyToAddress(acc.PK.PublicKey)
if strings.ToLower(acc.Addr.Hex()) != strings.ToLower(acc.Address) {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: given address not match with private key (%s), please check", acc.Address, acc.Addr))
return
}
if err := accountApprove(client, acc, env); err != nil {
if err := accountApproveWithPermit(client, acc, env); err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] do approve failed: %v", acc.Address, err))
return
}
//router, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client)
//if err != nil {
// addTofailed(acc)
// WriteLog(fmt.Sprintf("[%s] failed: failed to create router contract: %v", acc.Address, err))
// return
//}
router, err := buildparam.NewParamContract(common.HexToAddress(env.UniversalRouter), client)
if err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to create router contract: %v", acc.Address, err))
return
}
txopts := &bind.TransactOpts{
From: acc.Addr,
Signer: acc.SignTx,
GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)),
}
addNewTx := func(tx *ethtypes.Transaction) {
IncrTotalTx()
receipt := waitTx(client, tx)
for _, log := range receipt.Logs {
if log.Topics[0] == pancake.TransferTopic {
token, _ := erc20.NewTokenContract(common.HexToAddress(env.KLKO), client)
token, _ := erc20.NewTokenContract(common.HexToAddress(cfg.Pair.Token), client)
event, _ := token.ParseTransfer(*log)
if event.To == acc.Addr {
val, _ := new(big.Float).SetInt(event.Value).Float64()
......@@ -236,28 +343,25 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
IncrFinishedTx()
}
dec := new(big.Int).SetUint64(1000000000000000000)
fee := big.NewInt(10000)
for i := 0; i < cfg.Param.Count; i++ {
in := new(big.Int).Mul(big.NewInt(cfg.Param.Volume), dec)
in = new(big.Int).Div(in, big.NewInt(10)) // param volume 1 is 0.1
v3r, err := v3router.NewV3Router(common.HexToAddress(env.Router), client)
// calc amountOutMin with price and slippage.
amountOutMin, err := pancake.GetAmountOutMin(client, env, in, cfg.Param.Slippage, fee)
amountOutMin, err := pancake.GetAmountOutMin(cfg, client, env, in, cfg.Param.Slippage, fee)
if err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to get amount out min: %v", acc.Address, err))
return
}
param := pancake.ParamV3SwapExactIn{
Recipient: acc.Addr,
Recipient: common.HexToAddress(acc.Recipient),
AmountIn: in,
AmountOutMin: amountOutMin,
Path: nil,
PayerIsUser: true,
}
data, err := pancake.MakeV3SwapExactInData(env, param)
data, err := pancake.MakeV3SwapExactInData(env, param, cfg)
if err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to make swap data: %v", acc.Address, err))
......@@ -266,23 +370,7 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
inputs := make([][]byte, 0)
inputs = append(inputs, data)
deadline := time.Now().Unix() + cfg.Param.Deadline*60
//if execTx, err := router.Execute(txopts, []byte{byte(pancake.V3_SWAP_EXACT_IN)}, inputs, big.NewInt(deadline)); err != nil {
// addTofailed(acc)
// WriteLog(fmt.Sprintf("[%s] failed: failed execute swap: %v", acc.Address, err))
// return
//} else {
// addNewTx(execTx)
//}
if execTx, err := v3r.ExactInputSingle(txopts, v3router.ISwapRouterExactInputSingleParams{
TokenIn: common.HexToAddress(env.USDT),
TokenOut: common.HexToAddress(env.KLKO),
Recipient: acc.Addr,
AmountIn: in,
AmountOutMinimum: amountOutMin,
Deadline: big.NewInt(deadline),
Fee: fee,
SqrtPriceLimitX96: big.NewInt(0),
}); err != nil {
if execTx, err := router.Execute(txopts, []byte{byte(pancake.V3_SWAP_EXACT_IN)}, inputs, big.NewInt(deadline)); err != nil {
addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed execute swap: %v", acc.Address, err))
return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment