Skip to content

Commit

Permalink
add Support gas
Browse files Browse the repository at this point in the history
  • Loading branch information
cherry-yl-sh committed Mar 11, 2024
1 parent cd7aeda commit 3e5c9f7
Show file tree
Hide file tree
Showing 20 changed files with 259 additions and 19 deletions.
2 changes: 1 addition & 1 deletion common/model/api_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

type TryPayUserOpRequest struct {
ForceStrategyId string `json:"force_strategy_id"`
ForceNetwork types.NetWork `json:"force_network"`
ForceNetwork types.Network `json:"force_network"`
ForceToken string `json:"force_token"`
ForceEntryPointAddress string `json:"force_entrypoint_address"`
UserOperation UserOperationItem `json:"user_operation"`
Expand Down
5 changes: 3 additions & 2 deletions common/model/api_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ type TryPayUserOpResponse struct {
}

type ComputeGasResponse struct {
CallGasLimit uint64 `json:"call_gas_limit"`
GasPriceInWei uint64 `json:"gas_price_wei"` // wei
GasPriceInGwei *big.Float `json:"gas_price_gwei"`
GasPriceInEther string `json:"gas_price_ether"`
TokenCost string `json:"token_cost"`
Network types.NetWork `json:"network"`
Network types.Network `json:"network"`
Token types.TokenType `json:"token"`
UsdCost string `json:"usd_cost"`
BlobEnable bool `json:"blob_enable"`
Expand All @@ -36,7 +37,7 @@ type GetSupportEntryPointResponse struct {
type EntrypointDomain struct {
Address string `json:"address"`
Desc string `json:"desc"`
NetWork types.NetWork `json:"network"`
NetWork types.Network `json:"network"`
StrategyId string `json:"strategy_id"`
}

Expand Down
3 changes: 2 additions & 1 deletion common/model/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ type Strategy struct {
Id string `json:"id"`
EntryPointAddress string `json:"entrypoint_address"`
PayMasterAddress string `json:"paymaster_address"`
NetWork types.NetWork `json:"network"`
PayType types.PayType `json:"pay_type"`
NetWork types.Network `json:"network"`
Token types.TokenType `json:"token"`
Description string `json:"description"`
ExecuteRestriction StrategyExecuteRestriction `json:"execute_restriction"`
Expand Down
6 changes: 3 additions & 3 deletions common/model/user_operation.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package model

type UserOperationItem struct {
Sender string `json:"sender" binding:"required"`
Sender string `json:"sender" binding:"required,hexParam"`
Nonce string `json:"nonce" binding:"required"`
InitCode string `json:"init_code"`
CallData string `json:"call_data" binding:"required"`
Expand All @@ -10,6 +10,6 @@ type UserOperationItem struct {
PreVerificationGas string `json:"per_verification_gas" binding:"required"`
MaxFeePerGas string `json:"max_fee_per_gas" binding:"required"`
MaxPriorityFeePerGas string `json:"max_priority_fee_per_gas" binding:"required"`
Signature string `json:"signature"`
//paymasterAndData string `json:"paymaster_and_data"`
Signature string `json:"signature" binding:"required"`
PaymasterAndData string `json:"paymaster_and_data"`
}
14 changes: 10 additions & 4 deletions common/types/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ type NetworkInfo struct {
// Optimism Chain = "Optimism"
//)

type NetWork string
type Network string

const (
Ethereum NetWork = "ethereum"
Sepolia NetWork = "sepolia"
Arbitrum NetWork = "arbitrum"
Ethereum Network = "ethereum"
Sepolia Network = "sepolia"
Arbitrum Network = "arbitrum"
)

var TestNetWork = map[Network]bool{}

func init() {
TestNetWork[Sepolia] = true
}
9 changes: 9 additions & 0 deletions common/types/error_prefix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package types

type ErrorPrefix string

const (
ValidateParamError ErrorPrefix = "AA2"
ValidateUserOpError ErrorPrefix = "AA3"
ValidateGasError ErrorPrefix = "AA4"
)
8 changes: 8 additions & 0 deletions common/types/pay_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package types

type PayType string

const (
PayTypeVerifying PayType = "0"
PayTypeERC20 PayType = "1"
)
18 changes: 18 additions & 0 deletions common/utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import (
"AAStarCommunity/EthPaymaster_BackService/common/model"
"encoding/json"
"github.com/ethereum/go-ethereum/crypto"
"regexp"
"strconv"
)

var HexPattern = regexp.MustCompile(`^0x[a-fA-F\d]*$`)

func GenerateMockUserOperation() *model.UserOperationItem {
//TODO use config
return &model.UserOperationItem{
Expand All @@ -21,6 +25,20 @@ func GenerateMockUserOperation() *model.UserOperationItem {
Signature: "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c",
}
}
func ValidateHex(value string) bool {
if HexPattern.MatchString(value) {
return true
}
return false
}
func IsStringInUint64Range(s string) bool {
num, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return false
}
// 0 <= num <= MaxUint64
return num <= ^uint64(0)
}
func GenerateUserOperation() *model.UserOperationItem {
return &model.UserOperationItem{}
}
Expand Down
5 changes: 5 additions & 0 deletions common/utils/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ func TestSignUserOp(t *testing.T) {
fmt.Printf("singature: %s\n", singature)

}

func TestValidate(t *testing.T) {
userOp := GenerateMockUserOperation()
assert.True(t, ValidateHex(userOp.Sender))
}
11 changes: 11 additions & 0 deletions paymaster_data_generator/erc20_paymaster_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package paymaster_data_generator

import "AAStarCommunity/EthPaymaster_BackService/common/model"

type Erc20PaymasterGenerator struct {
}

func (e Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error) {
//ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount
return "0x", nil
}
7 changes: 7 additions & 0 deletions paymaster_data_generator/paymaster_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package paymaster_data_generator

import "AAStarCommunity/EthPaymaster_BackService/common/model"

type PaymasterGenerator interface {
GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error)
}
12 changes: 12 additions & 0 deletions paymaster_data_generator/vertifying_paymaster_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package paymaster_data_generator

import "AAStarCommunity/EthPaymaster_BackService/common/model"

type VerifyingPaymasterGenerator struct {
}

func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error) {
//verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature
return "0x", nil

}
18 changes: 17 additions & 1 deletion rpc_server/routers/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,36 @@ package routers

import (
"AAStarCommunity/EthPaymaster_BackService/common/model"
"AAStarCommunity/EthPaymaster_BackService/common/utils"
"AAStarCommunity/EthPaymaster_BackService/conf"
"AAStarCommunity/EthPaymaster_BackService/docs"
"AAStarCommunity/EthPaymaster_BackService/rpc_server/middlewares"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"io"
"net/http"
)

var hexParam validator.Func = func(fl validator.FieldLevel) bool {
param, ok := fl.Field().Interface().(string)
if ok {
return utils.ValidateHex(param)
}
return true
}

// SetRouters set routers
func SetRouters() (routers *gin.Engine) {
routers = gin.New()

if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
err := v.RegisterValidation("hexParam", hexParam)
if err != nil {
return nil
}
}
buildMod(routers)
buildRoute(routers)
routers.NoRoute(func(ctx *gin.Context) {
Expand Down
8 changes: 4 additions & 4 deletions service/chain_service/chain_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
)

var NetworkInfoMap map[types.NetWork]*types.NetworkInfo
var NetWorkClientMap map[types.NetWork]*ethclient.Client
var NetworkInfoMap map[types.Network]*types.NetworkInfo
var NetWorkClientMap map[types.Network]*ethclient.Client

func init() {
ConfigInit()
ClientInit()
}
func ConfigInit() {
//TODO api key secret store
NetworkInfoMap = map[types.NetWork]*types.NetworkInfo{
NetworkInfoMap = map[types.Network]*types.NetworkInfo{
types.Ethereum: {
Name: "ethereum",
RpcUrl: "https://eth-mainnet.g.alchemy.com/v2/bIZQS43-rJMgv2_SiHqfVvXa-Z1UGoGt",
Expand All @@ -27,7 +27,7 @@ func ConfigInit() {
}

func ClientInit() {
NetWorkClientMap = make(map[types.NetWork]*ethclient.Client)
NetWorkClientMap = make(map[types.Network]*ethclient.Client)
for chain, networkInfo := range NetworkInfoMap {
client, err := ethclient.Dial(networkInfo.RpcUrl)
if err != nil {
Expand Down
17 changes: 15 additions & 2 deletions service/chain_service/chain_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package chain_service
import (
"AAStarCommunity/EthPaymaster_BackService/common/types"
"context"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
"golang.org/x/xerrors"
"math/big"
)

var GweiFactor = new(big.Float).SetInt(big.NewInt(1e9))
var EthWeiFactor = new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))

func CheckContractAddressAccess(contract string, chain types.NetWork) (bool, error) {
func CheckContractAddressAccess(contract string, chain types.Network) (bool, error) {
if chain == "" {
return false, xerrors.Errorf("chain can not be empty")
}
Expand All @@ -32,7 +34,7 @@ func CheckContractAddressAccess(contract string, chain types.NetWork) (bool, err
}

// GetGasPrice return gas price in wei, gwei, ether
func GetGasPrice(chain types.NetWork) (*big.Int, *big.Float, *string, error) {
func GetGasPrice(chain types.Network) (*big.Int, *big.Float, *string, error) {
client, exist := NetWorkClientMap[chain]
if !exist {
return nil, nil, nil, xerrors.Errorf("chain Client [%s] not exist", chain)
Expand All @@ -50,3 +52,14 @@ func GetGasPrice(chain types.NetWork) (*big.Int, *big.Float, *string, error) {
gasPriceInEtherStr := gasPriceInEther.Text('f', 18)
return priceWei, gasPriceInGwei, &gasPriceInEtherStr, nil
}

func GetEntryPointDeposit(entrypoint string, depositAddress string) uint256.Int {
return uint256.Int{1}
}
func EstimateGasLimitAndCost(chain types.Network, msg ethereum.CallMsg) (uint64, error) {
client, exist := NetWorkClientMap[chain]
if !exist {
return 0, xerrors.Errorf("chain Client [%s] not exist", chain)
}
return client.EstimateGas(context.Background(), msg)
}
29 changes: 28 additions & 1 deletion service/dashboard_service/dashboard_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import (
"errors"
)

// TODO just Temp Mock
var mockStrategyMap = map[string]*model.Strategy{}
var payMasterSupport = map[string]bool{}
var entryPointSupport = map[string]bool{}

func init() {
mockStrategyMap["1"] = &model.Strategy{
Expand All @@ -16,11 +19,35 @@ func init() {
NetWork: types.Sepolia,
Token: types.USDT,
}
mockStrategyMap["2"] = &model.Strategy{
Id: "2",
EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57",
PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f",
NetWork: types.Sepolia,
Token: types.ETH,
}

entryPointSupport["0x0576a174D229E3cFA37253523E645A78A0C91B57"] = true
payMasterSupport["0x0000000000325602a77416A16136FDafd04b299f"] = true
}
func GetStrategyById(strategyId string) *model.Strategy {
return mockStrategyMap[strategyId]
}
func GetSupportEntryPoint() {

func GetSuitableStrategy(entrypoint string, chain types.NetWork, token string) (*model.Strategy, error) {
}
func GetSuitableStrategy(entrypoint string, chain types.Network, token string) (*model.Strategy, error) {
return nil, errors.New("not implemented")
}
func IsEntryPointsSupport(address string) bool {
if entryPointSupport[address] {
return true
}
return false
}
func IsPayMasterSupport(address string) bool {
if payMasterSupport[address] {
return true
}
return false
}
26 changes: 26 additions & 0 deletions service/gas_service/gas_computor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,39 @@ import (
"AAStarCommunity/EthPaymaster_BackService/common/model"
"AAStarCommunity/EthPaymaster_BackService/common/types"
"AAStarCommunity/EthPaymaster_BackService/service/chain_service"
"encoding/hex"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"golang.org/x/xerrors"
"strconv"
)

func ComputeGas(userOp *model.UserOperationItem, strategy *model.Strategy) (*model.ComputeGasResponse, error) {
priceInWei, gasPriceInGwei, gasPriceInEtherStr, getGasErr := chain_service.GetGasPrice(types.Sepolia)
//TODO calculate the maximum possible fee the account needs to pay (based on validation and call gas limits, and current gas values)
if getGasErr != nil {
return nil, getGasErr
}
sender := common.HexToAddress(userOp.Sender)
callData, _ := hex.DecodeString(userOp.CallData)
//
estimateCallGasLimit, _ := chain_service.EstimateGasLimitAndCost(strategy.NetWork, ethereum.CallMsg{
From: common.HexToAddress(strategy.EntryPointAddress),
To: &sender,
Data: callData,
})
userOpCallGasLimit, _ := strconv.ParseUint(userOp.CallGasLimit, 10, 64)
if estimateCallGasLimit > userOpCallGasLimit {
return nil, xerrors.Errorf("estimateCallGasLimit %d > userOpCallGasLimit %d", estimateCallGasLimit, userOpCallGasLimit)
}

// TODO get PaymasterCallGasLimit

return &model.ComputeGasResponse{
GasPriceInWei: priceInWei.Uint64(),
GasPriceInGwei: gasPriceInGwei,
GasPriceInEther: *gasPriceInEtherStr,
CallGasLimit: estimateCallGasLimit,
TokenCost: "0.0001",
Network: strategy.NetWork,
Token: strategy.Token,
Expand All @@ -24,5 +46,9 @@ func ComputeGas(userOp *model.UserOperationItem, strategy *model.Strategy) (*mod
}

func ValidateGas(userOp *model.UserOperationItem, gasComputeResponse *model.ComputeGasResponse) error {
//1.if ERC20 check address balacnce
//Validate the account’s deposit in the entryPoint is high enough to cover the max possible cost (cover the already-done verification and max execution gas)
//2 if Paymaster check paymaster balance
//The maxFeePerGas and maxPriorityFeePerGas are above a configurable minimum value that the client is willing to accept. At the minimum, they are sufficiently high to be included with the current block.basefee.
return nil
}
Loading

0 comments on commit 3e5c9f7

Please sign in to comment.