Commit 5860be39 authored by luxq's avatar luxq

update

parent 34b01480
...@@ -23,19 +23,11 @@ cd pancakeswaper ...@@ -23,19 +23,11 @@ cd pancakeswaper
make make
``` ```
#### 2. fill in the `accounts.json` file with the accounts you want to do swap for. #### 2. fill in the `accounts.csv` file with the accounts you want to do swap for.
The example of the `accounts.json` file is as follow: The example of the `accounts.csv` file is as follow:
```json ```csv
[ useraddress, privatekey, recipient
{ 0xeFbb75e446Ec2d8493B3d4d91aC3118953f69b55, 0x1111111111111111, 0xc437593d9C296bf9A5002522A86dad8a4d4Af808
"address": "0x",
"private": "0x"
},
{
"address": "0x",
"private": "0x"
}
]
``` ```
#### 4. change configure #### 4. change configure
...@@ -55,6 +47,12 @@ param: ...@@ -55,6 +47,12 @@ param:
# tx deadline, unit is minutes, set 0 to disable. # tx deadline, unit is minutes, set 0 to disable.
deadline: 20 deadline: 20
pair:
# pair address.
pair: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a"
# klko address
token: "0x215324115417a13879f865Dc5BB651B18A781a59"
rpc: rpc:
env: "bsc" env: "bsc"
pool: 20 pool: 20
...@@ -62,7 +60,7 @@ rpc: ...@@ -62,7 +60,7 @@ rpc:
log: log:
level: "debug" level: "debug"
users: "accounts.json" users: "accounts.csv"
``` ```
#### 5. run the program #### 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: ...@@ -12,6 +12,12 @@ param:
# tx deadline, unit is minutes, set 0 to disable. # tx deadline, unit is minutes, set 0 to disable.
deadline: 20 deadline: 20
pair:
# pair address.
pair: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a"
# klko address
token: "0x215324115417a13879f865Dc5BB651B18A781a59"
rpc: rpc:
env: "bsc" env: "bsc"
pool: 20 pool: 20
...@@ -19,4 +25,4 @@ rpc: ...@@ -19,4 +25,4 @@ rpc:
log: log:
level: "debug" level: "debug"
users: "accounts.json" users: "accounts.csv"
\ No newline at end of file \ No newline at end of file
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
type Config struct { type Config struct {
Log LogConfig `yaml:"log"` Log LogConfig `yaml:"log"`
Param ParamConfig `yaml:"param"` Param ParamConfig `yaml:"param"`
Pair PairConfig `yaml:"pair"`
Rpc RpcConfig `yaml:"rpc"` Rpc RpcConfig `yaml:"rpc"`
Users string `yaml:"users"` Users string `yaml:"users"`
} }
...@@ -25,6 +26,11 @@ type ParamConfig struct { ...@@ -25,6 +26,11 @@ type ParamConfig struct {
Deadline int64 `yaml:"deadline"` Deadline int64 `yaml:"deadline"`
} }
type PairConfig struct {
Pair string `yaml:"pair"`
Token string `yaml:"token"`
}
type RpcConfig struct { type RpcConfig struct {
Env string `yaml:"env"` Env string `yaml:"env"`
PoolSize int `yaml:"pool"` PoolSize int `yaml:"pool"`
......
package pancake package pancake
import ( import (
"code.wuban.net.cn/service/pancakeswapper/config"
"code.wuban.net.cn/service/pancakeswapper/contracts/buildparam" "code.wuban.net.cn/service/pancakeswapper/contracts/buildparam"
"code.wuban.net.cn/service/pancakeswapper/contracts/v3pool" "code.wuban.net.cn/service/pancakeswapper/contracts/v3pool"
"code.wuban.net.cn/service/pancakeswapper/types" "code.wuban.net.cn/service/pancakeswapper/types"
...@@ -30,7 +31,7 @@ func leftPadding(data []byte, length int) []byte { ...@@ -30,7 +31,7 @@ func leftPadding(data []byte, length int) []byte {
return append(padding, data...) return append(padding, data...)
} }
func MakeV3SwapExactInPathData(env types.Env) []byte { func MakeV3SwapExactInPathData(env types.Env, cfg *config.Config) []byte {
//0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3 //0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3
//0000000000000000000000000000000000000000000000001bc16d674ec80000 //0000000000000000000000000000000000000000000000001bc16d674ec80000
//0000000000000000000000000000000000000000000000002620b5d4cdab6c04 //0000000000000000000000000000000000000000000000002620b5d4cdab6c04
...@@ -40,7 +41,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte { ...@@ -40,7 +41,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte {
//55d398326f99059ff775485246999027b3197955002710215324115417a13879f865dc5bb651b18a781a59000000000000000000000000000000000000000000 //55d398326f99059ff775485246999027b3197955002710215324115417a13879f865dc5bb651b18a781a59000000000000000000000000000000000000000000
token0 := common.HexToAddress(env.USDT) token0 := common.HexToAddress(env.USDT)
token1 := common.HexToAddress(env.KLKO) token1 := common.HexToAddress(cfg.Pair.Token)
fee := big.NewInt(10000) fee := big.NewInt(10000)
data := make([]byte, 0) data := make([]byte, 0)
data = append(data, token0.Bytes()...) data = append(data, token0.Bytes()...)
...@@ -49,7 +50,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte { ...@@ -49,7 +50,7 @@ func MakeV3SwapExactInPathData(env types.Env) []byte {
return data return data
} }
func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn) ([]byte, error) { func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn, cfg *config.Config) ([]byte, error) {
//0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3 //0000000000000000000000003e3b4d16ce35840c28f90edb7f38e5bdd976c7e3
//0000000000000000000000000000000000000000000000000de0b6b3a7640000 //0000000000000000000000000000000000000000000000000de0b6b3a7640000
//00000000000000000000000000000000000000000000000012d0ee4f5819f972 //00000000000000000000000000000000000000000000000012d0ee4f5819f972
...@@ -59,7 +60,7 @@ func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn) ([]byte, err ...@@ -59,7 +60,7 @@ func MakeV3SwapExactInData(env types.Env, param ParamV3SwapExactIn) ([]byte, err
//55d398326f99059ff775485246999027b3197955002710215324115417a13879 //55d398326f99059ff775485246999027b3197955002710215324115417a13879
//f865dc5bb651b18a781a59000000000000000000000000000000000000000000 //f865dc5bb651b18a781a59000000000000000000000000000000000000000000
param.Path = MakeV3SwapExactInPathData(env) param.Path = MakeV3SwapExactInPathData(env, cfg)
buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI)) 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) 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) { ...@@ -103,10 +104,10 @@ func MakePermit2PermitData(acc *types.Account, env types.Env) ([]byte, error) {
// amountIn is the amount of input token (USDT) to swap. // 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%. // 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%. // 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) { slippage int64, feeRate *big.Int) (*big.Int, error) {
// get slot0 data. // get slot0 data.
pool := common.HexToAddress(env.Pool) pool := common.HexToAddress(cfg.Pair.Pair)
contract, err := v3pool.NewV3Pool(pool, client) contract, err := v3pool.NewV3Pool(pool, client)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -216,6 +217,7 @@ func MakePermit2PermitData2(acc *types.Account, env types.Env, client *ethclient ...@@ -216,6 +217,7 @@ func MakePermit2PermitData2(acc *types.Account, env types.Env, client *ethclient
// Pack the data // Pack the data
buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI)) buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI))
// todo: check method name.
data, err := buildAbi.Pack("buildParamPermit2", permitSingle, signature) data, err := buildAbi.Pack("buildParamPermit2", permitSingle, signature)
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -26,7 +26,7 @@ func (s *Swapper) Run() { ...@@ -26,7 +26,7 @@ func (s *Swapper) Run() {
work.WorkInit(env.ChainId) work.WorkInit(env.ChainId)
// 1. read account info from json file // 1. read account info from json file
accs := work.LoadAccounts(s.cfg.Users) accs := work.LoadAccountsFromCsv(s.cfg.Users)
work.SetTotalUser(len(accs)) work.SetTotalUser(len(accs))
waitCh := make(chan struct{}) waitCh := make(chan struct{})
......
...@@ -13,8 +13,9 @@ type Account struct { ...@@ -13,8 +13,9 @@ type Account struct {
Address string `json:"address"` Address string `json:"address"`
PrivateKey string `json:"private"` PrivateKey string `json:"private"`
//Nonce uint64 `json:"-"` //Nonce uint64 `json:"-"`
PK *ecdsa.PrivateKey `json:"-"` PK *ecdsa.PrivateKey `json:"-"`
Addr common.Address `json:"-"` Addr common.Address `json:"-"`
Recipient string `json:“recipient"`
} }
func (a *Account) sign(chainid *big.Int, tx *types.Transaction) (*types.Transaction, error) { func (a *Account) sign(chainid *big.Int, tx *types.Transaction) (*types.Transaction, error) {
......
...@@ -6,25 +6,23 @@ var ( ...@@ -6,25 +6,23 @@ var (
func init() { func init() {
allEnv["bsc"] = Env{ allEnv["bsc"] = Env{
//RPC: "https://bscnode.bitheart.org", RPC: "https://four.rpc.48.club",
RPC: "https://four.rpc.48.club", USDT: "0x55d398326f99059ff775485246999027b3197955",
USDT: "0x55d398326f99059ff775485246999027b3197955", Permit2: "0x31c2F6fcFf4F8759b3Bd5Bf0e1084A055615c768",
KLKO: "0x215324115417a13879f865Dc5BB651B18A781a59", // KLKO Router: "0x1b81D678ffb9C0263b24A97847620C99d213eB14",
Permit2: "0x31c2F6fcFf4F8759b3Bd5Bf0e1084A055615c768", UniversalRouter: "0x1A0A18AC4BECDDbd6389559687d1A73d8927E416",
Router: "0x1b81D678ffb9C0263b24A97847620C99d213eB14", ChainId: 56,
//Router: "0x1A0A18AC4BECDDbd6389559687d1A73d8927E416",
Pool: "0xcB0AE3B8337f0Cc35563e6b9fC357F2298C0D24a",
ChainId: 56,
} }
} }
type Env struct { type Env struct {
RPC string RPC string
USDT string USDT string
KLKO string //KLKO string
Permit2 string Permit2 string
Router string Router string // v3 router.
Pool string UniversalRouter string
//Pool string
ChainId int64 ChainId int64
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"code.wuban.net.cn/service/pancakeswapper/pancake" "code.wuban.net.cn/service/pancakeswapper/pancake"
"code.wuban.net.cn/service/pancakeswapper/types" "code.wuban.net.cn/service/pancakeswapper/types"
"context" "context"
"encoding/csv"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
...@@ -17,6 +18,7 @@ import ( ...@@ -17,6 +18,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
log "github.com/sirupsen/logrus"
"math/big" "math/big"
"os" "os"
"strings" "strings"
...@@ -25,6 +27,8 @@ import ( ...@@ -25,6 +27,8 @@ import (
var ( var (
failedHistory = make(chan *types.Account, 1000000) failedHistory = make(chan *types.Account, 1000000)
dec = new(big.Int).SetUint64(1000000000000000000)
fee = big.NewInt(10000)
) )
func LoadAccounts(file string) []*types.Account { func LoadAccounts(file string) []*types.Account {
...@@ -39,6 +43,48 @@ func LoadAccounts(file string) []*types.Account { ...@@ -39,6 +43,48 @@ func LoadAccounts(file string) []*types.Account {
} }
return accs 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) { func addTofailed(acc *types.Account) {
IncrFailedUser() IncrFailedUser()
failedHistory <- acc failedHistory <- acc
...@@ -58,17 +104,18 @@ func waitTx(client *ethclient.Client, tx *ethtypes.Transaction) *ethtypes.Receip ...@@ -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 cfg := config.Global
//permit2 := common.HexToAddress(env.Permit2) permit2 := common.HexToAddress(env.Permit2)
usdt, err := erc20.NewTokenContract(common.HexToAddress(env.USDT), client) usdt, err := erc20.NewTokenContract(common.HexToAddress(env.USDT), client)
if err != nil { if err != nil {
return fmt.Errorf("erc20.NewTokenContract failed: %v", err) return fmt.Errorf("erc20.NewTokenContract failed: %v", err)
} }
//router, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client) // router need set to Universal Router.
//if err != nil { router, err := buildparam.NewParamContract(common.HexToAddress(env.UniversalRouter), client)
// return fmt.Errorf("build param contract failed: %v", err) if err != nil {
//} return fmt.Errorf("build param contract failed: %v", err)
}
txopts := &bind.TransactOpts{ txopts := &bind.TransactOpts{
From: acc.Addr, From: acc.Addr,
...@@ -78,55 +125,42 @@ func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env) ...@@ -78,55 +125,42 @@ func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env)
addNewTx := func(tx *ethtypes.Transaction) { addNewTx := func(tx *ethtypes.Transaction) {
waitTx(client, tx) waitTx(client, tx)
} }
//if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil { allow, err := usdt.Allowance(&bind.CallOpts{
// return fmt.Errorf("usdt approve permit2 failed: %v", err) From: acc.Addr,
//} else { BlockNumber: nil,
// addNewTx(tx) Context: context.Background(),
//} }, acc.Addr, permit2)
if allow.Int64() == 0 {
// first approve usdt to permit2. if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
//if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil { return fmt.Errorf("usdt approve permit2 failed: %v", err)
if tx, err := usdt.Approve(txopts, common.HexToAddress(env.Router), abi.MaxUint256); err != nil { } else {
return fmt.Errorf("usdt approve pool failed: %v", err) addNewTx(tx)
} else { }
addNewTx(tx)
} }
//permitData, err := pancake.MakePermit2PermitData2(acc, env, client) permitData, err := pancake.MakePermit2PermitData2(acc, env, client)
//if err != nil { if err != nil {
// return fmt.Errorf("make permit data: %v", err) return fmt.Errorf("make permit data: %v", err)
//} }
//
//inputs := make([][]byte, 0)
//inputs = append(inputs, permitData)
//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 { // set permit with universal router execute.
// return fmt.Errorf("execute permit2 permit failed: %v", err) deadline := time.Now().Unix() + cfg.Param.Deadline*60
//} else { if execTx, err := router.Execute(txopts, []byte{byte(pancake.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline)); err != nil {
// addNewTx(execTx) return fmt.Errorf("execute permit2 permit failed: %v", err)
//} } else {
addNewTx(execTx)
}
return nil 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 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) usdt, err := erc20.NewTokenContract(common.HexToAddress(env.USDT), client)
if err != nil { if err != nil {
addTofailed(acc) return fmt.Errorf("erc20.NewTokenContract failed: %v", err)
WriteLog(fmt.Sprintf("[%s] failed: failed to create usdt contract: %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
} }
txopts := &bind.TransactOpts{ txopts := &bind.TransactOpts{
...@@ -134,47 +168,117 @@ func HandlerAccountApprove(acc *types.Account, env types.Env, idx uint) { ...@@ -134,47 +168,117 @@ func HandlerAccountApprove(acc *types.Account, env types.Env, idx uint) {
Signer: acc.SignTx, Signer: acc.SignTx,
GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)), GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)),
} }
addNewTx := func(tx *ethtypes.Transaction) { addNewTx := func(tx *ethtypes.Transaction) {
IncrTotalTx()
waitTx(client, tx) waitTx(client, tx)
IncrFinishedTx()
} }
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
}
// first approve usdt to permit2. func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil { 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) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed approve usdt to permit2 nft contract: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] failed: invalid private hex string: %v", acc.Address, pkstr))
return return
} else {
addNewTx(tx)
} }
acc.Addr = crypto.PubkeyToAddress(acc.PK.PublicKey)
permitData, err := pancake.MakePermit2PermitData(acc, env) if strings.ToLower(acc.Addr.Hex()) != strings.ToLower(acc.Address) {
if err != nil {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to make permit data: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] failed: given address not match with private key (%s), please check", acc.Address, acc.Addr))
return return
} }
inputs := make([][]byte, 0) if err := accountApprove(client, acc, env); err != nil {
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 {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed execute permit2 permit: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] do approve failed: %v", acc.Address, err))
return return
} else {
addNewTx(execTx)
} }
WriteLog(fmt.Sprintf("[%s] finish: have no more times to mint", acc.Address)) 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(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()
}
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(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
}
deadline := time.Now().Unix() + cfg.Param.Deadline*60
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 swap: %v", acc.Address, err))
return
} else {
addNewTx(execTx)
}
}
WriteLog(fmt.Sprintf("[%s] finish: have finished all swap", acc.Address))
IncrFinishedUser() 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 cfg := config.Global
client := clientpool.GetClient() client := clientpool.GetClient()
pkstr := acc.PrivateKey pkstr := acc.PrivateKey
...@@ -190,35 +294,38 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) { ...@@ -190,35 +294,38 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
return return
} }
acc.Addr = crypto.PubkeyToAddress(acc.PK.PublicKey) acc.Addr = crypto.PubkeyToAddress(acc.PK.PublicKey)
if strings.ToLower(acc.Addr.Hex()) != strings.ToLower(acc.Address) { if strings.ToLower(acc.Addr.Hex()) != strings.ToLower(acc.Address) {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: given address not match with private key (%s), please check", acc.Address, acc.Addr)) WriteLog(fmt.Sprintf("[%s] failed: given address not match with private key (%s), please check", acc.Address, acc.Addr))
return return
} }
if err := accountApprove(client, acc, env); err != nil {
if err := accountApproveWithPermit(client, acc, env); err != nil {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] do approve failed: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] do approve failed: %v", acc.Address, err))
return return
} }
//router, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client) router, err := buildparam.NewParamContract(common.HexToAddress(env.UniversalRouter), client)
//if err != nil { if err != nil {
// addTofailed(acc) addTofailed(acc)
// WriteLog(fmt.Sprintf("[%s] failed: failed to create router contract: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] failed: failed to create router contract: %v", acc.Address, err))
// return return
//} }
txopts := &bind.TransactOpts{ txopts := &bind.TransactOpts{
From: acc.Addr, From: acc.Addr,
Signer: acc.SignTx, Signer: acc.SignTx,
GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)), GasPrice: new(big.Int).Mul(big.NewInt(cfg.Param.GasPrice), big.NewInt(1e9)),
} }
addNewTx := func(tx *ethtypes.Transaction) { addNewTx := func(tx *ethtypes.Transaction) {
IncrTotalTx() IncrTotalTx()
receipt := waitTx(client, tx) receipt := waitTx(client, tx)
for _, log := range receipt.Logs { for _, log := range receipt.Logs {
if log.Topics[0] == pancake.TransferTopic { 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) event, _ := token.ParseTransfer(*log)
if event.To == acc.Addr { if event.To == acc.Addr {
val, _ := new(big.Float).SetInt(event.Value).Float64() val, _ := new(big.Float).SetInt(event.Value).Float64()
...@@ -236,28 +343,25 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) { ...@@ -236,28 +343,25 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
IncrFinishedTx() IncrFinishedTx()
} }
dec := new(big.Int).SetUint64(1000000000000000000)
fee := big.NewInt(10000)
for i := 0; i < cfg.Param.Count; i++ { for i := 0; i < cfg.Param.Count; i++ {
in := new(big.Int).Mul(big.NewInt(cfg.Param.Volume), dec) 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 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. // 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 { if err != nil {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to get amount out min: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] failed: failed to get amount out min: %v", acc.Address, err))
return return
} }
param := pancake.ParamV3SwapExactIn{ param := pancake.ParamV3SwapExactIn{
Recipient: acc.Addr, Recipient: common.HexToAddress(acc.Recipient),
AmountIn: in, AmountIn: in,
AmountOutMin: amountOutMin, AmountOutMin: amountOutMin,
Path: nil, Path: nil,
PayerIsUser: true, PayerIsUser: true,
} }
data, err := pancake.MakeV3SwapExactInData(env, param) data, err := pancake.MakeV3SwapExactInData(env, param, cfg)
if err != nil { if err != nil {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed to make swap data: %v", acc.Address, err)) 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) { ...@@ -266,23 +370,7 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
inputs := make([][]byte, 0) inputs := make([][]byte, 0)
inputs = append(inputs, data) inputs = append(inputs, data)
deadline := time.Now().Unix() + cfg.Param.Deadline*60 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 { 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 {
addTofailed(acc) addTofailed(acc)
WriteLog(fmt.Sprintf("[%s] failed: failed execute swap: %v", acc.Address, err)) WriteLog(fmt.Sprintf("[%s] failed: failed execute swap: %v", acc.Address, err))
return 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