Commit f68cffcd authored by vicotor's avatar vicotor

add test code.

parent baf36d8e
......@@ -5,14 +5,12 @@ 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"
log "github.com/sirupsen/logrus"
"math/big"
"strings"
"time"
......@@ -142,88 +140,68 @@ func GetAmountOutMin(cfg *config.Config, client *ethclient.Client, env types.Env
}
func MakePermit2PermitData2(acc *types.Account, env types.Env, client *ethclient.Client) ([]byte, error) {
//00000000000000000000000055d398326f99059ff775485246999027b3197955
//000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
//00000000000000000000000000000000000000000000000000000000681dd1ab
//0000000000000000000000000000000000000000000000000000000000000000
//0000000000000000000000001a0a18ac4becddbd6389559687d1a73d8927e416
//0000000000000000000000000000000000000000000000000000000067f64bb3
//00000000000000000000000000000000000000000000000000000000000000e0
//0000000000000000000000000000000000000000000000000000000000000041
//747b8fa98714e48b5db6e5585c8278ef7de03431ab30aed0b3d999cbf360d8db
//4fd9920bf48fbec49957def82ffa6e3441c6094b5cccd5ceee70ce19b1f96d11
//1c00000000000000000000000000000000000000000000000000000000000000
//00000000000000000000000055d398326f99059ff775485246999027b3197955
//000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
//0000000000000000000000000000000000000000000000000000000069d9bfbd
//0000000000000000000000000000000000000000000000000000000067f88c3d
//0000000000000000000000001a0a18ac4becddbd6389559687d1a73d8927e416
//0000000000000000000000000000000000000000000000000000000067f9ddbd
//00000000000000000000000000000000000000000000000000000000000000e0
//0000000000000000000000000000000000000000000000000000000000000041
//7e90d529be5a0c36f2a59226382e22b9b38e258584ca7cca8e6c74faf4734fbe
//42d5b2b152b6325729818115eb27b0421104fc5ad0b9a068d8212e1e17e8e8fd
//1c00000000000000000000000000000000000000000000000000000000000000
// Constants
year := int64(365 * 24 * 60 * 60)
hour := int64(60 * 60)
day := int64(60 * 60 * 24)
// 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),
}
expiration := big.NewInt(time.Now().Unix() + year)
chainId := big.NewInt(env.ChainId)
token := common.HexToAddress(env.USDT)
permit2Address := common.HexToAddress(env.Permit2)
amount := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 160), big.NewInt(1))
nonce := big.NewInt(time.Now().Unix())
// Get chain ID for domain separator
chainId, err := client.ChainID(context.Background())
signature, err := acc.SignTypedData(chainId, permit2Address, token, amount, expiration, nonce)
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,
// Create permit details
permitSingle := buildparam.IPancakePermitSingle{
Details: buildparam.IPancakePermitDetails{
Token: common.HexToAddress(env.USDT),
Amount: amount,
Expiration: expiration,
Nonce: 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
Spender: common.HexToAddress(env.UniversalRouter),
SigDeadline: big.NewInt(time.Now().Unix() + day),
}
// 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 {
log.WithError(err).Error("build permit2 permit")
return nil, err
}
// Remove method ID
data = data[4:]
return data, nil
}
......@@ -33,6 +33,7 @@ func (s *Swapper) Run() {
// 2. init account info
go func(w chan struct{}, accounts []*types.Account) {
grouptask.DoMultiTasks(s.cfg.Param.Routine, env, work.HandlerAccountSwap, accounts)
//grouptask.DoMultiTasks(s.cfg.Param.Routine, env, work.HandlerAccountSwapWithUniversalRouter, accounts)
w <- struct{}{}
}(waitCh, accs)
......
......@@ -2,7 +2,10 @@ package types
import (
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
......@@ -40,23 +43,66 @@ 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)
func (a *Account) SignTypedData(chainID *big.Int, permit2Address, tokenAddress common.Address,
amount *big.Int, expiration *big.Int, nonce *big.Int) ([]byte, error) {
mchainId := math.HexOrDecimal256(*chainID)
// 创建EIP-712结构化数据
typedData := apitypes.TypedData{
Types: apitypes.Types{
"EIP712Domain": []apitypes.Type{
{Name: "name", Type: "string"},
{Name: "version", Type: "string"},
{Name: "chainId", Type: "uint256"},
{Name: "verifyingContract", Type: "address"},
},
"TokenPermissions": []apitypes.Type{
{Name: "token", Type: "address"},
{Name: "amount", Type: "uint256"},
},
"PermitTransferFrom": []apitypes.Type{
{Name: "permitted", Type: "TokenPermissions"},
{Name: "nonce", Type: "uint256"},
{Name: "deadline", Type: "uint256"},
},
},
PrimaryType: "PermitTransferFrom",
Domain: apitypes.TypedDataDomain{
Name: "Permit2",
Version: "1",
ChainId: &mchainId,
VerifyingContract: permit2Address.Hex(),
},
Message: apitypes.TypedDataMessage{
"permitted": map[string]interface{}{
"token": tokenAddress.Hex(),
"amount": amount.String(),
},
"nonce": hexutil.EncodeUint64(nonce.Uint64()),
"deadline": expiration.String(),
},
}
domain, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
if err != nil {
return nil, err
return nil, fmt.Errorf("domain hash failed: %v", err)
}
// Sign the hash with the private key
sig, err := crypto.Sign(hash, a.PK)
permitHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
if err != nil {
return nil, err
return nil, fmt.Errorf("message hash failed: %v", err)
}
// Adjust V value for Ethereum standard
if sig[64] < 27 {
sig[64] += 27
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domain), string(permitHash)))
signHash := crypto.Keccak256(rawData)
signature, err := crypto.Sign(signHash, a.PK)
if err != nil {
return nil, fmt.Errorf("sign message failed: %v", err)
}
return sig, nil
signature[64] += 27
return signature, nil
}
......@@ -5,11 +5,13 @@ import (
"code.wuban.net.cn/service/pancakeswapper/config"
"code.wuban.net.cn/service/pancakeswapper/contracts/buildparam"
"code.wuban.net.cn/service/pancakeswapper/contracts/erc20"
router2 "code.wuban.net.cn/service/pancakeswapper/contracts/router"
"code.wuban.net.cn/service/pancakeswapper/contracts/v3router"
"code.wuban.net.cn/service/pancakeswapper/pancake"
"code.wuban.net.cn/service/pancakeswapper/types"
"context"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi"
......@@ -145,9 +147,18 @@ func accountApproveWithPermit(client *ethclient.Client, acc *types.Account, env
inputs := make([][]byte, 0)
inputs = append(inputs, permitData)
fmt.Println("permit input data is ", hex.EncodeToString(permitData))
deadline := time.Now().Unix() + cfg.Param.Deadline*60
routerAbi, _ := abi.JSON(strings.NewReader(router2.RouterMetaData.ABI))
txdata, err := routerAbi.Pack("execute0", []byte{byte(pancake.PERMIT2_PERMIT)}, inputs, big.NewInt(deadline))
if err != nil {
fmt.Println()
return fmt.Errorf("pack execute failed: %v", err)
}
fmt.Println("txdata is ", hex.EncodeToString(txdata))
// 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 {
......
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