Commit 090c2d86 authored by luxq's avatar luxq

update permit

parent 61f5d93f
#!/bin/bash
# build abi.json to go package.
abigen --abi=permit.json --pkg=permit --type=Permit --out=contract.go
This diff is collapsed.
This diff is collapsed.
#!/bin/bash
# build abi.json to go package.
abigen --abi=router.json --pkg=router --type=Router --out=contract.go
\ No newline at end of file
This diff is collapsed.
[{"inputs":[{"components":[{"internalType":"address","name":"permit2","type":"address"},{"internalType":"address","name":"weth9","type":"address"},{"internalType":"address","name":"seaportV1_5","type":"address"},{"internalType":"address","name":"seaportV1_4","type":"address"},{"internalType":"address","name":"openseaConduit","type":"address"},{"internalType":"address","name":"x2y2","type":"address"},{"internalType":"address","name":"looksRareV2","type":"address"},{"internalType":"address","name":"routerRewardsDistributor","type":"address"},{"internalType":"address","name":"looksRareRewardsDistributor","type":"address"},{"internalType":"address","name":"looksRareToken","type":"address"},{"internalType":"address","name":"v2Factory","type":"address"},{"internalType":"address","name":"v3Factory","type":"address"},{"internalType":"address","name":"v3Deployer","type":"address"},{"internalType":"bytes32","name":"v2InitCodeHash","type":"bytes32"},{"internalType":"bytes32","name":"v3InitCodeHash","type":"bytes32"},{"internalType":"address","name":"stableFactory","type":"address"},{"internalType":"address","name":"stableInfo","type":"address"},{"internalType":"address","name":"pancakeNFTMarket","type":"address"}],"internalType":"struct RouterParameters","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BalanceTooLow","type":"error"},{"inputs":[],"name":"BuyPancakeNFTFailed","type":"error"},{"inputs":[],"name":"BuyPunkFailed","type":"error"},{"inputs":[],"name":"ContractLocked","type":"error"},{"inputs":[],"name":"ETHNotAccepted","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandIndex","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"FromAddressIsNotOwner","type":"error"},{"inputs":[],"name":"InsufficientETH","type":"error"},{"inputs":[],"name":"InsufficientToken","type":"error"},{"inputs":[],"name":"InvalidBips","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandType","type":"uint256"}],"name":"InvalidCommandType","type":"error"},{"inputs":[],"name":"InvalidOwnerERC1155","type":"error"},{"inputs":[],"name":"InvalidOwnerERC721","type":"error"},{"inputs":[],"name":"InvalidPath","type":"error"},{"inputs":[],"name":"InvalidPoolAddress","type":"error"},{"inputs":[],"name":"InvalidPoolLength","type":"error"},{"inputs":[],"name":"InvalidReserves","type":"error"},{"inputs":[],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"SliceOutOfBounds","type":"error"},{"inputs":[],"name":"StableInvalidPath","type":"error"},{"inputs":[],"name":"StableTooLittleReceived","type":"error"},{"inputs":[],"name":"StableTooMuchRequested","type":"error"},{"inputs":[],"name":"TransactionDeadlinePassed","type":"error"},{"inputs":[],"name":"UnableToClaim","type":"error"},{"inputs":[],"name":"UnsafeCast","type":"error"},{"inputs":[],"name":"V2InvalidPath","type":"error"},{"inputs":[],"name":"V2TooLittleReceived","type":"error"},{"inputs":[],"name":"V2TooMuchRequested","type":"error"},{"inputs":[],"name":"V3InvalidAmountOut","type":"error"},{"inputs":[],"name":"V3InvalidCaller","type":"error"},{"inputs":[],"name":"V3InvalidSwap","type":"error"},{"inputs":[],"name":"V3TooLittleReceived","type":"error"},{"inputs":[],"name":"V3TooMuchRequested","type":"error"},{"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,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":true,"internalType":"address","name":"info","type":"address"}],"name":"SetStableSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"bytes","name":"looksRareClaim","type":"bytes"}],"name":"collectRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"pancakeV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_info","type":"address"}],"name":"setStableSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableSwapFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stableSwapInfo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
\ No newline at end of file
......@@ -4,11 +4,14 @@ import (
"code.wuban.net.cn/service/pancakeswapper/contracts/buildparam"
"code.wuban.net.cn/service/pancakeswapper/contracts/v3pool"
"code.wuban.net.cn/service/pancakeswapper/types"
"context"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"math/big"
"strings"
"time"
......@@ -122,7 +125,6 @@ func GetAmountOutMin(client *ethclient.Client, env types.Env, amountIn *big.Int,
priceX96Dec := new(big.Int).Mul(priceX96, tokenDec)
price := priceX96Dec.Div(priceX96Dec, new(big.Int).Exp(big.NewInt(2), big.NewInt(2*96), nil))
amountIn = new(big.Int).Mul(amountIn, tokenDec)
fee := new(big.Int).Div(new(big.Int).Mul(amountIn, feeRate), big.NewInt(1e6))
amountIn = amountIn.Sub(amountIn, fee)
fmt.Println("sub fee", amountIn.Text(10))
......@@ -137,3 +139,89 @@ func GetAmountOutMin(client *ethclient.Client, env types.Env, amountIn *big.Int,
return minAmountOut, nil
}
func MakePermit2PermitData2(acc *types.Account, env types.Env, client *ethclient.Client) ([]byte, error) {
// Constants
year := int64(365 * 24 * 60 * 60)
hour := int64(60 * 60)
// Create permit details
permitSingle := buildparam.IPancakePermitSingle{
Details: buildparam.IPancakePermitDetails{
Token: common.HexToAddress(env.USDT),
Amount: abi.MaxUint256,
Expiration: big.NewInt(time.Now().Unix() + year),
Nonce: big.NewInt(time.Now().Unix()),
},
Spender: common.HexToAddress(env.Router),
SigDeadline: big.NewInt(time.Now().Unix() + hour),
}
// Get chain ID for domain separator
chainId, err := client.ChainID(context.Background())
if err != nil {
return nil, err
}
// Get permit2 contract address
permit2Address := common.HexToAddress(env.Permit2)
// Create the domain separator
domain := apitypes.TypedDataDomain{
Name: "Permit2",
ChainId: math.NewHexOrDecimal256(chainId.Int64()),
VerifyingContract: permit2Address.Hex(),
}
// Create the types for EIP-712 signing
types := apitypes.Types{
"PermitSingle": []apitypes.Type{
{Name: "details", Type: "PermitDetails"},
{Name: "spender", Type: "address"},
{Name: "sigDeadline", Type: "uint256"},
},
"PermitDetails": []apitypes.Type{
{Name: "token", Type: "address"},
{Name: "amount", Type: "uint256"},
{Name: "expiration", Type: "uint256"},
{Name: "nonce", Type: "uint256"},
},
}
// Create the typed data message
message := map[string]interface{}{
"details": map[string]interface{}{
"token": permitSingle.Details.Token.Hex(),
"amount": permitSingle.Details.Amount,
"expiration": permitSingle.Details.Expiration,
"nonce": permitSingle.Details.Nonce,
},
"spender": permitSingle.Spender.Hex(),
"sigDeadline": permitSingle.SigDeadline,
}
// Create the typed data
typedData := apitypes.TypedData{
Types: types,
PrimaryType: "PermitSingle",
Domain: domain,
Message: message,
}
// Generate EIP-712 signature hash
signature, err := acc.SignTypedData(typedData)
if err != nil {
return nil, err
}
// Pack the data
buildAbi, _ := abi.JSON(strings.NewReader(buildparam.ParamContractMetaData.ABI))
data, err := buildAbi.Pack("buildParamPermit2", permitSingle, signature)
if err != nil {
return nil, err
}
// Remove method ID
data = data[4:]
return data, nil
}
......@@ -49,6 +49,7 @@ func (s *Swapper) Run() {
if failed > 0 {
fmt.Printf("all done, %d failed user info write in failed.json\n", failed)
} else {
fmt.Println(work.GetReport())
fmt.Println("all done, no failed user")
}
return
......
......@@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"math/big"
)
......@@ -37,3 +38,24 @@ func (a *Account) SignMessage(msg []byte) ([]byte, error) {
}
return sig, nil
}
func (a *Account) SignTypedData(typedData apitypes.TypedData) ([]byte, error) {
// Use the go-ethereum hash generator for EIP-712
hash, _, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return nil, err
}
// Sign the hash with the private key
sig, err := crypto.Sign(hash, a.PK)
if err != nil {
return nil, err
}
// Adjust V value for Ethereum standard
if sig[64] < 27 {
sig[64] += 27
}
return sig, nil
}
......@@ -64,10 +64,10 @@ func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env)
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, err := buildparam.NewParamContract(common.HexToAddress(env.Router), client)
//if err != nil {
// return fmt.Errorf("build param contract failed: %v", err)
//}
txopts := &bind.TransactOpts{
From: acc.Addr,
......@@ -77,29 +77,35 @@ func accountApprove(client *ethclient.Client, acc *types.Account, env types.Env)
addNewTx := func(tx *ethtypes.Transaction) {
waitTx(client, tx)
}
// first approve usdt to permit2.
if tx, err := usdt.Approve(txopts, permit2, abi.MaxUint256); err != nil {
return fmt.Errorf("usdt approve failed: %v", err)
return fmt.Errorf("usdt approve permit2 failed: %v", err)
} else {
addNewTx(tx)
}
permitData, err := pancake.MakePermit2PermitData(acc, env)
if err != nil {
return fmt.Errorf("make permit data: %v", err)
// 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.Pool), abi.MaxUint256); err != nil {
return fmt.Errorf("usdt approve pool failed: %v", err)
} else {
addNewTx(tx)
}
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)
//}
//
//inputs := make([][]byte, 0)
//inputs = append(inputs, permitData)
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.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline)); err != nil {
return fmt.Errorf("execute permit2 permit failed: %v", err)
} else {
addNewTx(execTx)
}
//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
}
......@@ -217,12 +223,12 @@ func HandlerAccountSwap(acc *types.Account, env types.Env, idx uint) {
val, _ := new(big.Float).SetInt(event.Value).Float64()
val = val / 1e18
WriteLog(fmt.Sprintf("[%s] receive %f token", acc.Address, val))
IncrReceiveToken(int(val))
IncrReceiveToken(val)
}
if event.From == acc.Addr {
val, _ := new(big.Float).SetInt(event.Value).Float64()
val = val / 1e18
IncrCostToken(int(val))
IncrCostToken(val)
}
}
}
......@@ -279,6 +285,7 @@ func Finish() int {
data, _ := json.MarshalIndent(failed, "", " ")
os.WriteFile("failed.json", data, 0666)
}
WriteFinished()
return len(failed)
}
......@@ -7,6 +7,29 @@ import (
"sync/atomic"
)
type FloatMetric struct {
mux sync.RWMutex
name string
val atomic.Value
}
func NewFlotMetric(name string) *FloatMetric {
m := &FloatMetric{name: name}
m.val.Store(float64(0.0))
return m
}
func (m *FloatMetric) Incr(n float64) {
m.mux.Lock()
defer m.mux.Unlock()
v := m.val.Load().(float64)
m.val.Store(v + n)
}
func (m *FloatMetric) Get() float64 {
return m.val.Load().(float64)
}
type Metric struct {
mux sync.RWMutex
name string
......@@ -51,8 +74,8 @@ var (
failedTx = NewMetric("failedTx")
finishedTx = NewMetric("finishedTx")
costToken = NewMetric("costToken")
receiveToken = NewMetric("receiveToken")
costToken = NewFlotMetric("costToken")
receiveToken = NewFlotMetric("receiveToken")
)
func SetTotalUser(cnt int) {
......@@ -79,12 +102,12 @@ func IncrFinishedTx() {
finishedTx.Incr()
}
func IncrReceiveToken(val int) {
receiveToken.Add(val)
func IncrReceiveToken(val float64) {
receiveToken.Incr(val)
}
func IncrCostToken(val int) {
costToken.Add(val)
func IncrCostToken(val float64) {
costToken.Incr(val)
}
func GetReport() string {
......@@ -92,6 +115,6 @@ func GetReport() string {
str = append(str, "REPORT\t\t\tFailed/Total\t\t\tFinished/Total")
str = append(str, fmt.Sprintf("USER\t\t\t%5d/%-5d\t\t\t\t%5d/%-5d", failedUser.Get(), totalUser.Get(), finishedUser.Get(), totalUser.Get()))
str = append(str, fmt.Sprintf("TX\t\t\t\t\t\t\t\t%5d/%-5d", finishedTx.Get(), totalTx.Get()))
str = append(str, fmt.Sprintf("%d Cost / %d Receive", costToken.Get(), receiveToken.Get()))
str = append(str, fmt.Sprintf("%f Cost / %f Receive", costToken.Get(), receiveToken.Get()))
return strings.Join(str, "\n")
}
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