diff --git a/common/model/api_response.go b/common/model/api_response.go index f771660a..76a17877 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -16,15 +16,13 @@ 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"` - Token types.TokenType `json:"token"` - UsdCost string `json:"usd_cost"` - BlobEnable bool `json:"blob_enable"` + GasInfo *GasPrice `json:"gas_info"` + TokenCost string `json:"token_cost"` + Network types.Network `json:"network"` + Token types.TokenType `json:"token"` + UsdCost string `json:"usd_cost"` + BlobEnable bool `json:"blob_enable"` + MaxFee big.Int `json:"max_fee"` } type PayReceipt struct { TransactionHash string `json:"transaction_hash"` diff --git a/common/model/gas_price.go b/common/model/gas_price.go new file mode 100644 index 00000000..27081a95 --- /dev/null +++ b/common/model/gas_price.go @@ -0,0 +1,12 @@ +package model + +import "math/big" + +type GasPrice struct { + MaxBasePriceWei *big.Int `json:"max_base_price_wei"` + MaxBasePriceGwei *big.Float `json:"max_base_price_gwei"` + MaxBasePriceEther *string `json:"max_base_price_ether"` + MaxPriorityPriceWei *big.Int `json:"max_priority_price_wei"` + MaxPriorityPriceGwei *big.Float `json:"max_priority_price_gwei"` + MaxPriorityPriceEther *string `json:"max_priority_price_ether"` +} diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 4214613f..827b7b99 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -10,13 +10,16 @@ import ( ) // UserOperation entrypoint v0.0.6 +// verificationGasLimit validateUserOp ,validatePaymasterUserOp limit +// callGasLimit calldata Execute gas limit +// preVerificationGas type UserOperation struct { Sender common.Address `json:"sender" mapstructure:"sender" binding:"required,hexParam"` Nonce *big.Int `json:"nonce" mapstructure:"nonce" binding:"required"` InitCode []byte `json:"initCode" mapstructure:"initCode" ` CallData []byte `json:"callData" mapstructure:"callData" binding:"required"` CallGasLimit *big.Int `json:"callGasLimit" mapstructure:"callGasLimit" binding:"required"` - VerificationGasList *big.Int `json:"verificationGasLimit" mapstructure:"verificationGasLimit" binding:"required"` + VerificationGasLimit *big.Int `json:"verificationGasLimit" mapstructure:"verificationGasLimit" binding:"required"` PreVerificationGas *big.Int `json:"preVerificationGas" mapstructure:"preVerificationGas" binding:"required"` MaxFeePerGas *big.Int `json:"maxFeePerGas" mapstructure:"maxFeePerGas" binding:"required"` MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas" mapstructure:"maxPriorityFeePerGas" binding:"required"` diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index 4c79045a..287fd4e3 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -1,6 +1,7 @@ package chain_service import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/types" "context" "github.com/ethereum/go-ethereum" @@ -33,23 +34,63 @@ func CheckContractAddressAccess(contract common.Address, chain types.Network) (b } // GetGasPrice return gas price in wei, gwei, ether -func GetGasPrice(chain types.Network) (*big.Int, *big.Float, *string, error) { +func GetGasPrice(chain types.Network) (*model.GasPrice, error) { client, exist := EthCompatibleNetWorkClientMap[chain] if !exist { - return nil, nil, nil, xerrors.Errorf("chain Client [%s] not exist", chain) + return nil, xerrors.Errorf("chain Client [%s] not exist", chain) } - priceWei, err := client.SuggestGasPrice(context.Background()) - if err != nil { - return nil, nil, nil, err + priceWei, priceWeiErr := client.SuggestGasPrice(context.Background()) + if priceWeiErr != nil { + return nil, priceWeiErr + } + priorityPriceWei, tiperr := client.SuggestGasTipCap(context.Background()) + if tiperr != nil { + return nil, tiperr } + result := model.GasPrice{} + result.MaxBasePriceWei = priceWei + result.MaxPriorityPriceWei = priorityPriceWei gasPriceInGwei := new(big.Float).SetInt(priceWei) gasPriceInGwei.Quo(gasPriceInGwei, GweiFactor) - gasPriceInEther := new(big.Float).SetInt(priceWei) gasPriceInEther.Quo(gasPriceInEther, EthWeiFactor) gasPriceInEtherStr := gasPriceInEther.Text('f', 18) - return priceWei, gasPriceInGwei, &gasPriceInEtherStr, nil + result.MaxBasePriceGwei = gasPriceInGwei + result.MaxBasePriceEther = &gasPriceInEtherStr + + priorityPriceInGwei := new(big.Float).SetInt(priorityPriceWei) + priorityPriceInGwei.Quo(priorityPriceInGwei, GweiFactor) + priorityPriceInEther := new(big.Float).SetInt(priorityPriceWei) + priorityPriceInEther.Quo(priorityPriceInEther, EthWeiFactor) + priorityPriceInEtherStr := priorityPriceInEther.Text('f', 18) + result.MaxPriorityPriceGwei = priorityPriceInGwei + result.MaxPriorityPriceEther = &priorityPriceInEtherStr + result.MaxPriorityPriceGwei = priorityPriceInGwei + result.MaxPriorityPriceEther = &priorityPriceInEtherStr + return &result, nil +} + +func GetGas(netWork types.Network) (*big.Int, error) { + client, exist := EthCompatibleNetWorkClientMap[netWork] + if !exist { + return nil, xerrors.Errorf("chain Client [%s] not exist", netWork) + } + head, erro := client.HeaderByNumber(context.Background(), nil) + if erro != nil { + return nil, erro + } + return head.BaseFee, nil +} +func GetPriorityFee(netWork types.Network) (*big.Int, *big.Float) { + client, exist := EthCompatibleNetWorkClientMap[netWork] + if !exist { + return nil, nil + } + priceWei, _ := client.SuggestGasTipCap(context.Background()) + gasPriceInGwei := new(big.Float).SetInt(priceWei) + gasPriceInGwei.Quo(gasPriceInGwei, GweiFactor) + return priceWei, gasPriceInGwei } func GetEntryPointDeposit(entrypoint string, depositAddress string) uint256.Int { diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index 186cb738..ca88e5c3 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -21,7 +21,12 @@ func TestGetGasPrice(t *testing.T) { fmt.Printf("priceWeiInt %d\n", priceWeiInt) fmt.Printf("gasPriceInGwei %f\n", gasPriceInGwei) fmt.Printf("gasPriceInEtherStr %s\n", *gasPriceInEtherStr) + baseFee, _ := GetGas(types.Ethereum) + fmt.Printf("baseFee %d\n", baseFee.Uint64()) + priorFee, priorFeeIGwei := GetPriorityFee(types.Ethereum) + fmt.Printf("priorFee %d\n", priorFee.Uint64()) + fmt.Printf("priorFeeIGwei %f\n", priorFeeIGwei) } func TestGethClient(t *testing.T) { diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index 1acefa37..36dca222 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -2,18 +2,18 @@ package gas_service import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" + "math/big" ) func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.ComputeGasResponse, error) { - priceInWei, gasPriceInGwei, gasPriceInEtherStr, getGasErr := chain_service.GetGasPrice(types.Sepolia) + gasPrice, gasPriceErr := chain_service.GetGasPrice(strategy.NetWork) //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 + if gasPriceErr != nil { + return nil, gasPriceErr } estimateCallGasLimit, _ := chain_service.EstimateGasLimitAndCost(strategy.NetWork, ethereum.CallMsg{ From: common.HexToAddress(strategy.EntryPointAddress), @@ -24,21 +24,32 @@ func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.C if estimateCallGasLimit > userOpCallGasLimit { return nil, xerrors.Errorf("estimateCallGasLimit %d > userOpCallGasLimit %d", estimateCallGasLimit, userOpCallGasLimit) } + //x := gasPrice.MaxBasePriceWei.Int64() + gasPrice.MaxPriorityPriceWei.Int64() + //maxFeePerGas := (x, userOp.MaxFeePerGas.Uint64()) + payMasterPostGasLimit := GetPayMasterGasLimit() - // TODO get PaymasterCallGasLimit + maxGasLimit := big.NewInt(0).Add(userOp.CallGasLimit, userOp.VerificationGasLimit) + maxGasLimit = maxGasLimit.Add(maxGasLimit, payMasterPostGasLimit) + maxFee := new(big.Int).Mul(maxGasLimit, gasPrice.MaxBasePriceWei) + // TODO get PaymasterCallGasLimit + tokenCost := GetTokenCost(*maxFee, userOp, *strategy) return &model.ComputeGasResponse{ - GasPriceInWei: priceInWei.Uint64(), - GasPriceInGwei: gasPriceInGwei, - GasPriceInEther: *gasPriceInEtherStr, - CallGasLimit: estimateCallGasLimit, - TokenCost: "0.0001", - Network: strategy.NetWork, - Token: strategy.Token, - UsdCost: "0.4", - BlobEnable: strategy.Enable4844, + GasInfo: gasPrice, + TokenCost: tokenCost, + Network: strategy.NetWork, + Token: strategy.Token, + UsdCost: "0.4", + BlobEnable: strategy.Enable4844, + MaxFee: *maxFee, }, nil } +func GetPayMasterGasLimit() *big.Int { + return nil +} +func GetTokenCost(maxFee big.Int, userOp *model.UserOperation, strategy model.Strategy) string { + return "0.0001" +} func ValidateGas(userOp *model.UserOperation, gasComputeResponse *model.ComputeGasResponse) error { //1.if ERC20 check address balacnce diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 7a087726..36817cab 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -31,7 +31,7 @@ func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperation) err } func ValidateUserOp(userOp *model.UserOperation) error { - if userOp.PreVerificationGas.Cmp(MinPreVerificationGas) < 0 { + if userOp.PreVerificationGas.Cmp(MinPreVerificationGas) == -1 { return xerrors.Errorf("preVerificationGas is less than 21000") }