From 2e58ace10741d192c37c127cb2f1180b498a52b9 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 7 Mar 2024 21:20:58 +0800 Subject: [PATCH 01/47] optimize get API --- common/model/api_request.go | 14 -------------- common/model/api_response.go | 14 ++++++++++++++ docs/docs.go | 8 ++++++++ docs/swagger.json | 8 ++++++++ docs/swagger.yaml | 5 +++++ rpc_server/api/v1/get_support_entrypoint.go | 14 +++++--------- rpc_server/api/v1/get_support_strategy.go | 15 ++++----------- rpc_server/api/v1/try_pay_user_operation.go | 2 +- .../operator/get_support_entry_point_execute.go | 6 ++++-- service/operator/get_support_strategy_execute.go | 2 +- service/operator/try_pay_user_op_execute.go | 11 +++-------- 11 files changed, 53 insertions(+), 46 deletions(-) diff --git a/common/model/api_request.go b/common/model/api_request.go index 29a1c2f2..5069dcc7 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -22,17 +22,3 @@ func (request *TryPayUserOpRequest) Validate() error { } return nil } - -type GetSupportEntrypointRequest struct { -} - -func (request *GetSupportEntrypointRequest) Validate() error { - return nil -} - -type GetSupportStrategyRequest struct { -} - -func (request *GetSupportStrategyRequest) Validate() error { - return nil -} diff --git a/common/model/api_response.go b/common/model/api_response.go index 4a361925..7f1818e9 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -28,3 +28,17 @@ type PayReceipt struct { TransactionHash string `json:"transaction_hash"` Sponsor string `json:"sponsor"` } + +type GetSupportEntryPointResponse struct { + EntrypointDomains []EntrypointDomain `json:"entrypoints"` +} +type EntrypointDomain struct { + Address string `json:"address"` + Desc string `json:"desc"` + NetWork types.NetWork `json:"network"` + StrategyId string `json:"strategy_id"` +} + +type GetSupportStrategyResponse struct { + Strategies []Strategy `json:"strategies"` +} diff --git a/docs/docs.go b/docs/docs.go index 0e07f2c2..b27877dd 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -75,6 +75,14 @@ const docTemplate = `{ "tags": [ "Sponsor" ], + "parameters": [ + { + "type": "string", + "description": "network", + "name": "network", + "in": "query" + } + ], "responses": { "200": { "description": "OK" diff --git a/docs/swagger.json b/docs/swagger.json index e9a7fd87..0350bbd5 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -64,6 +64,14 @@ "tags": [ "Sponsor" ], + "parameters": [ + { + "type": "string", + "description": "network", + "name": "network", + "in": "query" + } + ], "responses": { "200": { "description": "OK" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b20ce651..59d6bbc4 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -97,6 +97,11 @@ paths: consumes: - application/json description: get the support entrypoint + parameters: + - description: network + in: query + name: network + type: string responses: "200": description: OK diff --git a/rpc_server/api/v1/get_support_entrypoint.go b/rpc_server/api/v1/get_support_entrypoint.go index d3e0a0b8..da677771 100644 --- a/rpc_server/api/v1/get_support_entrypoint.go +++ b/rpc_server/api/v1/get_support_entrypoint.go @@ -14,25 +14,21 @@ import ( // @Accept json // @Product json // @Router /api/v1/get-support-entrypoint [GET] +// @Param network query string false "network" // @Success 200 // @Security JWT func GetSupportEntrypoint(c *gin.Context) { - request := model.GetSupportEntrypointRequest{} response := model.GetResponse() //1. API validate - if err := c.ShouldBindJSON(&request); err != nil { - errStr := fmt.Sprintf("Request Error [%v]", err) - response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) - return - } - if err := request.Validate(); err != nil { - errStr := fmt.Sprintf("Request Error [%v]", err) + network := c.Query("network") + if network == "" { + errStr := fmt.Sprintf("Request Error [network is empty]") response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) return } //2. recall service - result, err := operator.GetSupportEntrypointExecute(&request) + result, err := operator.GetSupportEntrypointExecute(network) if err != nil { errStr := fmt.Sprintf("%v", err) response.SetHttpCode(http.StatusInternalServerError).FailCode(c, http.StatusInternalServerError, errStr) diff --git a/rpc_server/api/v1/get_support_strategy.go b/rpc_server/api/v1/get_support_strategy.go index 76ce005a..63b587e1 100644 --- a/rpc_server/api/v1/get_support_strategy.go +++ b/rpc_server/api/v1/get_support_strategy.go @@ -17,22 +17,15 @@ import ( // @Router /api/v1/get-support-strategy [GET] // @Security JWT func GetSupportStrategy(c *gin.Context) { - request := model.GetSupportStrategyRequest{} response := model.GetResponse() - - //1. API validate - if err := c.ShouldBindJSON(&request); err != nil { - errStr := fmt.Sprintf("Request Error [%v]", err) - response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) - return - } - if err := request.Validate(); err != nil { - errStr := fmt.Sprintf("Request Error [%v]", err) + network := c.Query("network") + if network == "" { + errStr := fmt.Sprintf("Request Error [network is empty]") response.SetHttpCode(http.StatusBadRequest).FailCode(c, http.StatusBadRequest, errStr) return } - if result, err := operator.GetSupportStrategyExecute(&request); err != nil { + if result, err := operator.GetSupportStrategyExecute(network); err != nil { errStr := fmt.Sprintf("%v", err) response.SetHttpCode(http.StatusInternalServerError).FailCode(c, http.StatusInternalServerError, errStr) return diff --git a/rpc_server/api/v1/try_pay_user_operation.go b/rpc_server/api/v1/try_pay_user_operation.go index b9ce5e1a..2694e26f 100644 --- a/rpc_server/api/v1/try_pay_user_operation.go +++ b/rpc_server/api/v1/try_pay_user_operation.go @@ -40,7 +40,7 @@ func TryPayUserOperation(c *gin.Context) { response.SetHttpCode(http.StatusInternalServerError).FailCode(c, http.StatusInternalServerError, errStr) return } else { - response.WithData(result).Success(c) + response.WithDataSuccess(c, result) return } } diff --git a/service/operator/get_support_entry_point_execute.go b/service/operator/get_support_entry_point_execute.go index b3f5cd9c..6c17a7b9 100644 --- a/service/operator/get_support_entry_point_execute.go +++ b/service/operator/get_support_entry_point_execute.go @@ -2,6 +2,8 @@ package operator import "AAStarCommunity/EthPaymaster_BackService/common/model" -func GetSupportEntrypointExecute(request *model.GetSupportEntrypointRequest) (*model.Result, error) { - return &model.Result{}, nil +func GetSupportEntrypointExecute(network string) (*model.GetSupportEntryPointResponse, error) { + return &model.GetSupportEntryPointResponse{ + EntrypointDomains: make([]model.EntrypointDomain, 0), + }, nil } diff --git a/service/operator/get_support_strategy_execute.go b/service/operator/get_support_strategy_execute.go index b0cd18f4..8fe58223 100644 --- a/service/operator/get_support_strategy_execute.go +++ b/service/operator/get_support_strategy_execute.go @@ -4,6 +4,6 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" ) -func GetSupportStrategyExecute(request *model.GetSupportStrategyRequest) (*model.Result, error) { +func GetSupportStrategyExecute(network string) (*model.Result, error) { return &model.Result{}, nil } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index f7c01853..6144587b 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -12,7 +12,7 @@ import ( "golang.org/x/xerrors" ) -func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.Result, error) { +func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserOpResponse, error) { // validator if err := businessParamValidate(request); err != nil { return nil, err @@ -46,7 +46,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.Result, err return nil, payError } paymasterSignature := getPayMasterSignature(strategy, &userOp) - var result = model.TryPayUserOpResponse{ + var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, EntryPointAddress: strategy.EntryPointAddress, PayMasterAddress: strategy.PayMasterAddress, @@ -55,12 +55,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.Result, err GasInfo: gasResponse, } - return &model.Result{ - Code: 200, - Data: result, - Message: "message", - Cost: "cost", - }, nil + return result, nil } func businessParamValidate(request *model.TryPayUserOpRequest) error { From 9bb3951ebec866a8bfb9b3a0ca28d96d735798fc Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 7 Mar 2024 21:28:10 +0800 Subject: [PATCH 02/47] add GetSupportStrategy --- docs/docs.go | 8 ++++++++ docs/swagger.json | 8 ++++++++ docs/swagger.yaml | 5 +++++ rpc_server/api/v1/get_support_strategy.go | 1 + 4 files changed, 22 insertions(+) diff --git a/docs/docs.go b/docs/docs.go index b27877dd..a7837d6a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -107,6 +107,14 @@ const docTemplate = `{ "tags": [ "Sponsor" ], + "parameters": [ + { + "type": "string", + "description": "network", + "name": "network", + "in": "query" + } + ], "responses": { "200": { "description": "OK" diff --git a/docs/swagger.json b/docs/swagger.json index 0350bbd5..1f1f8b81 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -96,6 +96,14 @@ "tags": [ "Sponsor" ], + "parameters": [ + { + "type": "string", + "description": "network", + "name": "network", + "in": "query" + } + ], "responses": { "200": { "description": "OK" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 59d6bbc4..b53d21a3 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -114,6 +114,11 @@ paths: consumes: - application/json description: get the support strategy + parameters: + - description: network + in: query + name: network + type: string produces: - application/json responses: diff --git a/rpc_server/api/v1/get_support_strategy.go b/rpc_server/api/v1/get_support_strategy.go index 63b587e1..8cd0ab48 100644 --- a/rpc_server/api/v1/get_support_strategy.go +++ b/rpc_server/api/v1/get_support_strategy.go @@ -14,6 +14,7 @@ import ( // @Accept json // @Produce json // @Success 200 +// @Param network query string false "network" // @Router /api/v1/get-support-strategy [GET] // @Security JWT func GetSupportStrategy(c *gin.Context) { From cd7aedaaf366e7c246db5d9de243c10dacc0e4f0 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 8 Mar 2024 11:02:36 +0800 Subject: [PATCH 03/47] change response --- common/model/api_response.go | 1 + common/types/token.go | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/model/api_response.go b/common/model/api_response.go index 7f1818e9..e0175ee2 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -10,6 +10,7 @@ type TryPayUserOpResponse struct { EntryPointAddress string `json:"entrypoint_address"` PayMasterAddress string `json:"paymaster_address"` PayMasterSignature string `json:"paymaster_signature"` + PayMasterAndData string `json:"paymaster_and_data"` PayReceipt *PayReceipt `json:"pay_receipt"` GasInfo *ComputeGasResponse `json:"gas_info"` } diff --git a/common/types/token.go b/common/types/token.go index f5321605..7aaf6b13 100644 --- a/common/types/token.go +++ b/common/types/token.go @@ -3,6 +3,7 @@ package types type TokenType string const ( - USDT TokenType = "USDT" - ETH TokenType = "ETH" + USDT TokenType = "usdt" + ETH TokenType = "eth" + OP TokenType = "op" ) From 3e5c9f7862911da53f0314cca606697bc8c0468f Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 11 Mar 2024 22:44:25 +0800 Subject: [PATCH 04/47] add Support gas --- common/model/api_request.go | 2 +- common/model/api_response.go | 5 +- common/model/strategy.go | 3 +- common/model/user_operation.go | 6 +- common/types/chain.go | 14 +++-- common/types/error_prefix.go | 9 +++ common/types/pay_type.go | 8 +++ common/utils/util.go | 18 ++++++ common/utils/util_test.go | 5 ++ .../erc20_paymaster_generator.go | 11 ++++ .../paymaster_generator.go | 7 +++ .../vertifying_paymaster_generator.go | 12 ++++ rpc_server/routers/boot.go | 18 +++++- service/chain_service/chain_config.go | 8 +-- service/chain_service/chain_service.go | 17 +++++- .../dashboard_service/dashboard_service.go | 29 +++++++++- service/gas_service/gas_computor.go | 26 +++++++++ service/operator/try_pay_user_op_execute.go | 23 ++++++++ service/pay_service/pay_service.go | 1 + service/validator_service/basic_validator.go | 56 +++++++++++++++++++ 20 files changed, 259 insertions(+), 19 deletions(-) create mode 100644 common/types/error_prefix.go create mode 100644 common/types/pay_type.go create mode 100644 paymaster_data_generator/erc20_paymaster_generator.go create mode 100644 paymaster_data_generator/paymaster_generator.go create mode 100644 paymaster_data_generator/vertifying_paymaster_generator.go diff --git a/common/model/api_request.go b/common/model/api_request.go index 5069dcc7..6a52f9ce 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -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"` diff --git a/common/model/api_response.go b/common/model/api_response.go index e0175ee2..dcb0d4b4 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -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"` @@ -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"` } diff --git a/common/model/strategy.go b/common/model/strategy.go index a86516c0..8d02f8cf 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -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"` diff --git a/common/model/user_operation.go b/common/model/user_operation.go index c1fb22b5..1bfd2361 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -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"` @@ -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"` } diff --git a/common/types/chain.go b/common/types/chain.go index fa0e68d1..b4f0c507 100644 --- a/common/types/chain.go +++ b/common/types/chain.go @@ -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 +} diff --git a/common/types/error_prefix.go b/common/types/error_prefix.go new file mode 100644 index 00000000..8cb95325 --- /dev/null +++ b/common/types/error_prefix.go @@ -0,0 +1,9 @@ +package types + +type ErrorPrefix string + +const ( + ValidateParamError ErrorPrefix = "AA2" + ValidateUserOpError ErrorPrefix = "AA3" + ValidateGasError ErrorPrefix = "AA4" +) diff --git a/common/types/pay_type.go b/common/types/pay_type.go new file mode 100644 index 00000000..258a39d9 --- /dev/null +++ b/common/types/pay_type.go @@ -0,0 +1,8 @@ +package types + +type PayType string + +const ( + PayTypeVerifying PayType = "0" + PayTypeERC20 PayType = "1" +) diff --git a/common/utils/util.go b/common/utils/util.go index faef363c..621b6ddd 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -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{ @@ -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{} } diff --git a/common/utils/util_test.go b/common/utils/util_test.go index f9574b11..e6d69edb 100644 --- a/common/utils/util_test.go +++ b/common/utils/util_test.go @@ -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)) +} diff --git a/paymaster_data_generator/erc20_paymaster_generator.go b/paymaster_data_generator/erc20_paymaster_generator.go new file mode 100644 index 00000000..735af168 --- /dev/null +++ b/paymaster_data_generator/erc20_paymaster_generator.go @@ -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 +} diff --git a/paymaster_data_generator/paymaster_generator.go b/paymaster_data_generator/paymaster_generator.go new file mode 100644 index 00000000..f7f935b3 --- /dev/null +++ b/paymaster_data_generator/paymaster_generator.go @@ -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) +} diff --git a/paymaster_data_generator/vertifying_paymaster_generator.go b/paymaster_data_generator/vertifying_paymaster_generator.go new file mode 100644 index 00000000..05ec5d6f --- /dev/null +++ b/paymaster_data_generator/vertifying_paymaster_generator.go @@ -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 + +} diff --git a/rpc_server/routers/boot.go b/rpc_server/routers/boot.go index 70263d43..a8ab5d12 100644 --- a/rpc_server/routers/boot.go +++ b/rpc_server/routers/boot.go @@ -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) { diff --git a/service/chain_service/chain_config.go b/service/chain_service/chain_config.go index 3ce2b73d..d4240b59 100644 --- a/service/chain_service/chain_config.go +++ b/service/chain_service/chain_config.go @@ -5,8 +5,8 @@ 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() @@ -14,7 +14,7 @@ func init() { } 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", @@ -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 { diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index 0a43ca0e..fbb86e59 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -3,7 +3,9 @@ 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" ) @@ -11,7 +13,7 @@ import ( 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") } @@ -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) @@ -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) +} diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 0aa0b4c0..ba5feec6 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -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{ @@ -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 +} diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index 37c0b65c..aab3a666 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -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, @@ -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 } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 6144587b..1787d110 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -2,7 +2,9 @@ package operator import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/conf" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "AAStarCommunity/EthPaymaster_BackService/service/gas_service" @@ -45,6 +47,9 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO if payError != nil { return nil, payError } + paymasterAndData := getPayMasterAndData(strategy, &userOp) + userOp.PaymasterAndData = paymasterAndData + //validatePaymasterUserOp paymasterSignature := getPayMasterSignature(strategy, &userOp) var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, @@ -52,6 +57,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO PayMasterAddress: strategy.PayMasterAddress, PayReceipt: payReceipt, PayMasterSignature: paymasterSignature, + PayMasterAndData: paymasterAndData, GasInfo: gasResponse, } @@ -62,7 +68,14 @@ func businessParamValidate(request *model.TryPayUserOpRequest) error { if request.ForceStrategyId == "" && (request.ForceToken == "" || request.ForceNetwork == "") { return xerrors.Errorf("Token And Network Must Set When ForceStrategyId Is Empty") } + if conf.Environment.IsDevelopment() && request.ForceNetwork != "" { + if types.TestNetWork[request.ForceNetwork] { + return xerrors.Errorf("Test Network Not Support") + } + } + //recall simulate? //UserOp Validate + //check nonce if err := validator_service.ValidateUserOp(&request.UserOperation); err != nil { return err } @@ -96,6 +109,16 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } +func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperationItem) string { + //TODO + if strategy.PayType == types.PayTypeERC20 { + return "" + } + if strategy.PayType == types.PayTypeVerifying { + return "" + } + return "" +} func strategyGenerate(request *model.TryPayUserOpRequest) (*model.Strategy, error) { if forceStrategyId := request.ForceStrategyId; forceStrategyId != "" { diff --git a/service/pay_service/pay_service.go b/service/pay_service/pay_service.go index 86ae6fc0..45f11298 100644 --- a/service/pay_service/pay_service.go +++ b/service/pay_service/pay_service.go @@ -20,6 +20,7 @@ func (e *EthereumPayService) GetReceipt() { } func (e *EthereumPayService) Pay() error { + //1.if validate Paymaster //TODO implement me return nil } diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index d52effca..b7dfe4de 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -2,7 +2,11 @@ package validator_service import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" + "encoding/hex" + "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" ) @@ -23,7 +27,59 @@ func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperationItem) } func ValidateUserOp(userOp *model.UserOperationItem) error { + + if err := checkSender(userOp, types.Sepolia); err != nil { + return err + } + if !utils.IsStringInUint64Range(userOp.Nonce) { + return xerrors.Errorf("nonce is not in uint64 range") + } + + //If initCode is not empty, parse its first 20 bytes as a factory address. Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses global state, it must be staked - see reputation, throttling and banning section for details. + //The verificationGasLimit is sufficiently low (<= MAX_VERIFICATION_GAS) and the preVerificationGas is sufficiently high (enough to pay for the calldata gas cost of serializing the UserOperation plus PRE_VERIFICATION_OVERHEAD_GAS) // check Sender is valid ,if sender is invalid And InitCode empty, return error + // // nonce is valid + //validate trusted entrypoint + return nil +} +func checkSender(userOp *model.UserOperationItem, netWork types.Network) error { + //check sender + if userOp.Sender != "" { + if ok, err := chain_service.CheckContractAddressAccess(userOp.Sender, netWork); err != nil { + return err + } else if !ok { + return xerrors.Errorf("sender address not exist in [%s] network", netWork) + } + //check balance + } + if userOp.InitCode == "" { + return xerrors.Errorf("initCode can not be empty if sender is empty") + } + if err := checkInitCode(userOp.InitCode, netWork); err != nil { + + } + return nil +} +func checkInitCode(initCode string, network types.Network) error { + initCodeByte, err := hex.DecodeString(initCode) + if err != nil { + return xerrors.Errorf("initCode is not hex string %s", initCode) + } + if len(initCodeByte) < 20 { + return xerrors.Errorf("initCode is not valid %s", initCode) + } + factoryAddress := common.BytesToAddress(initCodeByte[:20]) + if ok, err := chain_service.CheckContractAddressAccess(factoryAddress.String(), network); err != nil { + return err + } else if !ok { + return xerrors.Errorf("sender address not exist in [%s] network", network) + } + // TODO checkFactoryAddress stack + //parse its first 20 bytes as a factory address. Record whether the factory is staked, + //factory and factoryData - either both exist, or none + + //parse its first 20 bytes as a factory address. Record whether the factory is staked, + //factory and factoryData - either both exist, or none return nil } From abf88400caa19dba3de54c52eb759ebc761397ff Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 12 Mar 2024 18:01:08 +0800 Subject: [PATCH 05/47] add userop convert --- common/model/api_request.go | 12 +- common/model/api_response.go | 2 +- common/model/strategy.go | 1 + common/model/user_operation.go | 104 +++++++++++++++++- common/types/entrypoint_tag.go | 8 ++ common/utils/util.go | 41 ++++--- common/utils/util_test.go | 20 +++- go.mod | 1 + go.sum | 2 + .../erc20_paymaster_generator.go | 2 +- .../paymaster_generator.go | 2 +- .../vertifying_paymaster_generator.go | 2 +- service/chain_service/chain_config.go | 6 +- service/chain_service/chain_service.go | 11 +- service/chain_service/chain_test.go | 6 +- service/gas_service/gas_computor.go | 15 +-- .../get_support_entry_point_execute.go | 2 +- service/operator/try_pay_user_op_execute.go | 62 ++++++----- .../operator/try_pay_user_op_execute_test.go | 2 +- service/validator_service/basic_validator.go | 56 +++++----- 20 files changed, 247 insertions(+), 110 deletions(-) create mode 100644 common/types/entrypoint_tag.go diff --git a/common/model/api_request.go b/common/model/api_request.go index 6a52f9ce..16defc1c 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -6,12 +6,12 @@ import ( ) type TryPayUserOpRequest struct { - ForceStrategyId string `json:"force_strategy_id"` - ForceNetwork types.Network `json:"force_network"` - ForceToken string `json:"force_token"` - ForceEntryPointAddress string `json:"force_entrypoint_address"` - UserOperation UserOperationItem `json:"user_operation"` - Extra interface{} `json:"extra"` + ForceStrategyId string `json:"force_strategy_id"` + ForceNetwork types.Network `json:"force_network"` + ForceToken string `json:"force_token"` + ForceEntryPointAddress string `json:"force_entrypoint_address"` + UserOp map[string]any `json:"user_operation"` + Extra interface{} `json:"extra"` } func (request *TryPayUserOpRequest) Validate() error { diff --git a/common/model/api_response.go b/common/model/api_response.go index dcb0d4b4..f771660a 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -32,7 +32,7 @@ type PayReceipt struct { } type GetSupportEntryPointResponse struct { - EntrypointDomains []EntrypointDomain `json:"entrypoints"` + EntrypointDomains *[]EntrypointDomain `json:"entrypoints"` } type EntrypointDomain struct { Address string `json:"address"` diff --git a/common/model/strategy.go b/common/model/strategy.go index 8d02f8cf..4c78e607 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -5,6 +5,7 @@ import "AAStarCommunity/EthPaymaster_BackService/common/types" type Strategy struct { Id string `json:"id"` EntryPointAddress string `json:"entrypoint_address"` + EntryPointTag types.EntrypointTag `json:"entrypoint_tag"` PayMasterAddress string `json:"paymaster_address"` PayType types.PayType `json:"pay_type"` NetWork types.Network `json:"network"` diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 1bfd2361..4214613f 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -1,15 +1,109 @@ package model -type UserOperationItem struct { +import ( + "encoding/hex" + "github.com/ethereum/go-ethereum/common" + "github.com/mitchellh/mapstructure" + "golang.org/x/xerrors" + "math/big" + "reflect" +) + +// UserOperation entrypoint v0.0.6 +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"` + 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"` + Signature []byte `json:"signature" mapstructure:"signature" binding:"required"` + PaymasterAndData []byte `json:"paymasterAndData" mapstructure:"paymasterAndData"` +} + +// PackUserOperation entrypoint v0.0.67 +type PackUserOperation struct { 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"` - CallGasLimit string `json:"call_gas_limit" binding:"required"` - VerificationGasList string `json:"verification_gas_list" binding:"required"` - PreVerificationGas string `json:"per_verification_gas" binding:"required"` + AccountGasLimit string `json:"account_gas_limit" binding:"required"` + PreVerificationGas string `json:"pre_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" binding:"required"` PaymasterAndData string `json:"paymaster_and_data"` + Signature string `json:"signature" binding:"required"` +} + +func NewUserOp(userOp *map[string]any) (*UserOperation, error) { + + var result UserOperation + // Convert map to struct + decodeConfig := &mapstructure.DecoderConfig{ + DecodeHook: decodeOpTypes, + Result: &result, + ErrorUnset: true, + MatchName: exactFieldMatch, + } + decoder, err := mapstructure.NewDecoder(decodeConfig) + if err != nil { + return nil, err + } + if err := decoder.Decode(userOp); err != nil { + return nil, xerrors.Errorf("data [%w] convert failed: [%w]", userOp, err) + } + + return &result, nil +} + +func exactFieldMatch(mapKey, fieldName string) bool { + return mapKey == fieldName +} + +func decodeOpTypes( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + // String to common.Address conversion + if f == reflect.String && t == reflect.Array { + return common.HexToAddress(data.(string)), nil + } + + // String to big.Int conversion + if f == reflect.String && t == reflect.Struct { + n := new(big.Int) + n, ok := n.SetString(data.(string), 0) + if !ok { + return nil, xerrors.Errorf("bigInt conversion failed") + } + return n, nil + } + + // Float64 to big.Int conversion + if f == reflect.Float64 && t == reflect.Struct { + n, ok := data.(float64) + if !ok { + return nil, xerrors.Errorf("bigInt conversion failed") + } + return big.NewInt(int64(n)), nil + } + + // String to []byte conversion + if f == reflect.String && t == reflect.Slice { + byteStr := data.(string) + if len(byteStr) < 2 || byteStr[:2] != "0x" { + return nil, xerrors.Errorf("not byte string") + } + + b, err := hex.DecodeString(byteStr[2:]) + if err != nil { + return nil, err + } + return b, nil + } + + return data, nil } diff --git a/common/types/entrypoint_tag.go b/common/types/entrypoint_tag.go new file mode 100644 index 00000000..cea0ab4c --- /dev/null +++ b/common/types/entrypoint_tag.go @@ -0,0 +1,8 @@ +package types + +type EntrypointTag string + +const ( + EntrypointV06 EntrypointTag = "v0.6" + EntryPointV07 EntrypointTag = "v0.7" +) diff --git a/common/utils/util.go b/common/utils/util.go index 621b6ddd..b91dedf7 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -2,6 +2,7 @@ package utils import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "encoding/hex" "encoding/json" "github.com/ethereum/go-ethereum/crypto" "regexp" @@ -10,20 +11,23 @@ import ( var HexPattern = regexp.MustCompile(`^0x[a-fA-F\d]*$`) -func GenerateMockUserOperation() *model.UserOperationItem { +func GenerateMockUserOperation() *map[string]any { //TODO use config - return &model.UserOperationItem{ - Sender: "0x4A2FD3215420376DA4eD32853C19E4755deeC4D1", - Nonce: "1", - InitCode: "0x", - CallData: "0xb61d27f6000000000000000000000000c206b552ab127608c3f666156c8e03a8471c72df000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", - CallGasLimit: "39837", - VerificationGasList: "100000", - PreVerificationGas: "44020", - MaxFeePerGas: "1743509478", - MaxPriorityFeePerGas: "1500000000", - Signature: "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", + var MockUserOpData = map[string]any{ + "sender": "0x4A2FD3215420376DA4eD32853C19E4755deeC4D1", + "nonce": "1", + "initCode": "0xe19e9755942bb0bd0cccce25b1742596b8a8250b3bf2c3e700000000000000000000000078d4f01f56b982a3b03c4e127a5d3afa8ebee6860000000000000000000000008b388a082f370d8ac2e2b3997e9151168bd09ff50000000000000000000000000000000000000000000000000000000000000000", + "callData": "0xb61d27f6000000000000000000000000c206b552ab127608c3f666156c8e03a8471c72df000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "callGasLimit": "39837", + "verificationGasLimit": "100000", + "maxFeePerGas": "44020", + "maxPriorityFeePerGas": "1743509478", + "paymasterAndData": "0x", + "preVerificationGas": "44020", + "signature": "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", } + + return &MockUserOpData } func ValidateHex(value string) bool { if HexPattern.MatchString(value) { @@ -39,11 +43,18 @@ func IsStringInUint64Range(s string) bool { // 0 <= num <= MaxUint64 return num <= ^uint64(0) } -func GenerateUserOperation() *model.UserOperationItem { - return &model.UserOperationItem{} +func GenerateUserOperation() *model.UserOperation { + return &model.UserOperation{} +} +func EncodeToStringWithPrefix(data []byte) string { + res := hex.EncodeToString(data) + if res[:2] != "0x" { + return "0x" + res + } + return res } -func SignUserOp(privateKeyHex string, userOp *model.UserOperationItem) ([]byte, error) { +func SignUserOp(privateKeyHex string, userOp *model.UserOperation) ([]byte, error) { serializedUserOp, err := json.Marshal(userOp) if err != nil { diff --git a/common/utils/util_test.go b/common/utils/util_test.go index e6d69edb..0beff9be 100644 --- a/common/utils/util_test.go +++ b/common/utils/util_test.go @@ -1,6 +1,7 @@ package utils import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" "crypto/ecdsa" "encoding/hex" "fmt" @@ -24,15 +25,28 @@ func TestSignUserOp(t *testing.T) { //privateKeyHex: 1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421 //publicKey: 044eaed6b1f16e60354156fa334a094affc76d7b7061875a0b04290af9a14cc14ce2bce6ceba941856bd55c63f8199f408fff6495ce9d4c76899055972d23bdb3e //address: 0x0E1375d18a4A2A867bEfe908E87322ad031386a6 - signByte, err := SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", GenerateMockUserOperation()) + userOp, newErr := model.NewUserOp(GenerateMockUserOperation()) + if newErr != nil { + fmt.Println(newErr) + } + signByte, err := SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) assert.NoError(t, err) fmt.Printf("signByte: %x\n", signByte) singature := hex.EncodeToString(signByte) fmt.Printf("singature: %s\n", singature) +} +func TestNewUserOp(t *testing.T) { + userOp, newErr := model.NewUserOp(GenerateMockUserOperation()) + if newErr != nil { + fmt.Println(newErr) + } + //initcode byte to string + fmt.Printf("userOp: %s\n", hex.EncodeToString(userOp.InitCode)) + } func TestValidate(t *testing.T) { - userOp := GenerateMockUserOperation() - assert.True(t, ValidateHex(userOp.Sender)) + //userOp := GenerateMockUserOperation() + //assert.True(t, ValidateHex(userOp.Sender)) } diff --git a/go.mod b/go.mod index 62750d97..86443055 100644 --- a/go.mod +++ b/go.mod @@ -52,6 +52,7 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index 3050129d..3b06b2bf 100644 --- a/go.sum +++ b/go.sum @@ -169,6 +169,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= diff --git a/paymaster_data_generator/erc20_paymaster_generator.go b/paymaster_data_generator/erc20_paymaster_generator.go index 735af168..b055c1c1 100644 --- a/paymaster_data_generator/erc20_paymaster_generator.go +++ b/paymaster_data_generator/erc20_paymaster_generator.go @@ -5,7 +5,7 @@ import "AAStarCommunity/EthPaymaster_BackService/common/model" type Erc20PaymasterGenerator struct { } -func (e Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error) { +func (e Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { //ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount return "0x", nil } diff --git a/paymaster_data_generator/paymaster_generator.go b/paymaster_data_generator/paymaster_generator.go index f7f935b3..b6f1fdcb 100644 --- a/paymaster_data_generator/paymaster_generator.go +++ b/paymaster_data_generator/paymaster_generator.go @@ -3,5 +3,5 @@ package paymaster_data_generator import "AAStarCommunity/EthPaymaster_BackService/common/model" type PaymasterGenerator interface { - GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error) + GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) } diff --git a/paymaster_data_generator/vertifying_paymaster_generator.go b/paymaster_data_generator/vertifying_paymaster_generator.go index 05ec5d6f..7709f90f 100644 --- a/paymaster_data_generator/vertifying_paymaster_generator.go +++ b/paymaster_data_generator/vertifying_paymaster_generator.go @@ -5,7 +5,7 @@ import "AAStarCommunity/EthPaymaster_BackService/common/model" type VerifyingPaymasterGenerator struct { } -func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperationItem) (string, error) { +func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature return "0x", nil diff --git a/service/chain_service/chain_config.go b/service/chain_service/chain_config.go index d4240b59..7171319e 100644 --- a/service/chain_service/chain_config.go +++ b/service/chain_service/chain_config.go @@ -6,7 +6,7 @@ import ( ) var NetworkInfoMap map[types.Network]*types.NetworkInfo -var NetWorkClientMap map[types.Network]*ethclient.Client +var EthCompatibleNetWorkClientMap map[types.Network]*ethclient.Client func init() { ConfigInit() @@ -27,13 +27,13 @@ func ConfigInit() { } func ClientInit() { - NetWorkClientMap = make(map[types.Network]*ethclient.Client) + EthCompatibleNetWorkClientMap = make(map[types.Network]*ethclient.Client) for chain, networkInfo := range NetworkInfoMap { client, err := ethclient.Dial(networkInfo.RpcUrl) if err != nil { panic(err) } - NetWorkClientMap[chain] = client + EthCompatibleNetWorkClientMap[chain] = client continue } } diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index fbb86e59..4c79045a 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -13,17 +13,16 @@ import ( 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 common.Address, chain types.Network) (bool, error) { if chain == "" { return false, xerrors.Errorf("chain can not be empty") } - contractAddress := common.HexToAddress(contract) - client, exist := NetWorkClientMap[chain] + client, exist := EthCompatibleNetWorkClientMap[chain] if !exist { return false, xerrors.Errorf("chain Client [%s] not exist", chain) } - code, err := client.CodeAt(context.Background(), contractAddress, nil) + code, err := client.CodeAt(context.Background(), contract, nil) if err != nil { return false, err } @@ -35,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) { - client, exist := NetWorkClientMap[chain] + client, exist := EthCompatibleNetWorkClientMap[chain] if !exist { return nil, nil, nil, xerrors.Errorf("chain Client [%s] not exist", chain) } @@ -57,7 +56,7 @@ 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] + client, exist := EthCompatibleNetWorkClientMap[chain] if !exist { return 0, xerrors.Errorf("chain Client [%s] not exist", chain) } diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index 6831ad39..186cb738 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -4,12 +4,14 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "context" "fmt" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "testing" ) func TestCheckContractAddressAccess(t *testing.T) { - res, err := CheckContractAddressAccess("0x0576a174D229E3cFA37253523E645A78A0C91B57", types.Sepolia) + address := "0x0576a174D229E3cFA37253523E645A78A0C91B57" + res, err := CheckContractAddressAccess(common.HexToAddress(address), types.Sepolia) assert.NoError(t, err) assert.True(t, res) } @@ -23,7 +25,7 @@ func TestGetGasPrice(t *testing.T) { } func TestGethClient(t *testing.T) { - client, _ := NetWorkClientMap[types.Sepolia] + client, _ := EthCompatibleNetWorkClientMap[types.Sepolia] num, _ := client.BlockNumber(context.Background()) assert.NotEqual(t, 0, num) fmt.Println(num) diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index aab3a666..1acefa37 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -4,28 +4,23 @@ 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) { +func ComputeGas(userOp *model.UserOperation, 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, + To: &userOp.Sender, + Data: userOp.CallData, }) - userOpCallGasLimit, _ := strconv.ParseUint(userOp.CallGasLimit, 10, 64) + userOpCallGasLimit := userOp.CallGasLimit.Uint64() if estimateCallGasLimit > userOpCallGasLimit { return nil, xerrors.Errorf("estimateCallGasLimit %d > userOpCallGasLimit %d", estimateCallGasLimit, userOpCallGasLimit) } @@ -45,7 +40,7 @@ func ComputeGas(userOp *model.UserOperationItem, strategy *model.Strategy) (*mod }, nil } -func ValidateGas(userOp *model.UserOperationItem, gasComputeResponse *model.ComputeGasResponse) error { +func ValidateGas(userOp *model.UserOperation, 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 diff --git a/service/operator/get_support_entry_point_execute.go b/service/operator/get_support_entry_point_execute.go index 6c17a7b9..68cc59e2 100644 --- a/service/operator/get_support_entry_point_execute.go +++ b/service/operator/get_support_entry_point_execute.go @@ -4,6 +4,6 @@ import "AAStarCommunity/EthPaymaster_BackService/common/model" func GetSupportEntrypointExecute(network string) (*model.GetSupportEntryPointResponse, error) { return &model.GetSupportEntryPointResponse{ - EntrypointDomains: make([]model.EntrypointDomain, 0), + EntrypointDomains: &[]model.EntrypointDomain{}, }, nil } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 1787d110..08fb56b0 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -11,6 +11,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/service/pay_service" "AAStarCommunity/EthPaymaster_BackService/service/validator_service" "encoding/hex" + "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" ) @@ -19,48 +20,60 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO if err := businessParamValidate(request); err != nil { return nil, err } - userOp := request.UserOperation - // getStrategy var strategy *model.Strategy - if stg, err := strategyGenerate(request); err != nil { + // getStrategy + strategy, generateErr := strategyGenerate(request) + if generateErr != nil { + return nil, generateErr + } + if strategy.EntryPointTag != types.EntrypointV06 { + return nil, xerrors.Errorf("Not Support EntryPointTag: [%w]", strategy.EntryPointTag) + } + + userOp, newUserOpError := model.NewUserOp(&request.UserOp) + if newUserOpError != nil { + return nil, newUserOpError + } + + if err := validator_service.ValidateStrategy(strategy, userOp); err != nil { return nil, err - } else if err = validator_service.ValidateStrategy(stg, &userOp); err != nil { + } + //recall simulate? + //UserOp Validate + //check nonce + if err := validator_service.ValidateUserOp(userOp); err != nil { return nil, err - } else { - strategy = stg } - //base Strategy and UserOp computeGas - gasResponse, gasComputeError := gas_service.ComputeGas(&userOp, strategy) + gasResponse, gasComputeError := gas_service.ComputeGas(userOp, strategy) if gasComputeError != nil { return nil, gasComputeError } //validate gas - if err := gas_service.ValidateGas(&userOp, gasResponse); err != nil { + if err := gas_service.ValidateGas(userOp, gasResponse); err != nil { return nil, err } //pay - payReceipt, payError := executePay(strategy, &userOp, gasResponse) + payReceipt, payError := executePay(strategy, userOp, gasResponse) if payError != nil { return nil, payError } - paymasterAndData := getPayMasterAndData(strategy, &userOp) + paymasterAndData := getPayMasterAndData(strategy, userOp) userOp.PaymasterAndData = paymasterAndData //validatePaymasterUserOp - paymasterSignature := getPayMasterSignature(strategy, &userOp) + paymasterSignature := getPayMasterSignature(strategy, userOp) var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, EntryPointAddress: strategy.EntryPointAddress, PayMasterAddress: strategy.PayMasterAddress, PayReceipt: payReceipt, PayMasterSignature: paymasterSignature, - PayMasterAndData: paymasterAndData, + PayMasterAndData: utils.EncodeToStringWithPrefix(paymasterAndData), GasInfo: gasResponse, } - return result, nil } @@ -73,15 +86,10 @@ func businessParamValidate(request *model.TryPayUserOpRequest) error { return xerrors.Errorf("Test Network Not Support") } } - //recall simulate? - //UserOp Validate - //check nonce - if err := validator_service.ValidateUserOp(&request.UserOperation); err != nil { - return err - } + if request.ForceEntryPointAddress != "" && request.ForceNetwork != "" { // check Address is available in NetWork - if ok, err := chain_service.CheckContractAddressAccess(request.ForceEntryPointAddress, request.ForceNetwork); err != nil { + if ok, err := chain_service.CheckContractAddressAccess(common.HexToAddress(request.ForceEntryPointAddress), request.ForceNetwork); err != nil { return err } else if !ok { return xerrors.Errorf("ForceEntryPointAddress: [%s] not exist in [%s] network", request.ForceEntryPointAddress, request.ForceNetwork) @@ -90,7 +98,7 @@ func businessParamValidate(request *model.TryPayUserOpRequest) error { return nil } -func executePay(strategy *model.Strategy, userOp *model.UserOperationItem, gasResponse *model.ComputeGasResponse) (*model.PayReceipt, error) { +func executePay(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (*model.PayReceipt, error) { //1.Recharge ethereumPayservice := pay_service.EthereumPayService{} if err := ethereumPayservice.Pay(); err != nil { @@ -105,19 +113,19 @@ func executePay(strategy *model.Strategy, userOp *model.UserOperationItem, gasRe Sponsor: "aastar", }, nil } -func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperationItem) string { +func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation) string { signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } -func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperationItem) string { +func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation) []byte { //TODO if strategy.PayType == types.PayTypeERC20 { - return "" + return []byte("ERC20") } if strategy.PayType == types.PayTypeVerifying { - return "" + return []byte("Verifying") } - return "" + return []byte("ETH") } func strategyGenerate(request *model.TryPayUserOpRequest) (*model.Strategy, error) { diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 39a11329..49905aff 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -20,6 +20,6 @@ func TestTryPayUserOpExecute(t *testing.T) { func getMockTryPayUserOpRequest() *model.TryPayUserOpRequest { return &model.TryPayUserOpRequest{ ForceStrategyId: "1", - UserOperation: *utils.GenerateMockUserOperation(), + UserOp: *utils.GenerateMockUserOperation(), } } diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index b7dfe4de..7a087726 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -3,14 +3,18 @@ package validator_service import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/types" - "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" - "encoding/hex" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" + "math/big" ) -func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperationItem) error { +var MinPreVerificationGas *big.Int + +func init() { + MinPreVerificationGas = big.NewInt(21000) +} +func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperation) error { if strategy == nil { return xerrors.Errorf("empty strategy") } @@ -18,7 +22,7 @@ func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperationItem) return xerrors.Errorf("empty strategy network") } // check Paymaster - ok, err := chain_service.CheckContractAddressAccess(strategy.PayMasterAddress, strategy.NetWork) + ok, err := chain_service.CheckContractAddressAccess(common.HexToAddress(strategy.PayMasterAddress), strategy.NetWork) if !ok || err != nil { return err } @@ -26,12 +30,16 @@ func ValidateStrategy(strategy *model.Strategy, userOp *model.UserOperationItem) return nil } -func ValidateUserOp(userOp *model.UserOperationItem) error { +func ValidateUserOp(userOp *model.UserOperation) error { + if userOp.PreVerificationGas.Cmp(MinPreVerificationGas) < 0 { + return xerrors.Errorf("preVerificationGas is less than 21000") + } if err := checkSender(userOp, types.Sepolia); err != nil { return err } - if !utils.IsStringInUint64Range(userOp.Nonce) { + + if !userOp.Nonce.IsInt64() { return xerrors.Errorf("nonce is not in uint64 range") } @@ -43,34 +51,28 @@ func ValidateUserOp(userOp *model.UserOperationItem) error { //validate trusted entrypoint return nil } -func checkSender(userOp *model.UserOperationItem, netWork types.Network) error { +func checkSender(userOp *model.UserOperation, netWork types.Network) error { //check sender - if userOp.Sender != "" { - if ok, err := chain_service.CheckContractAddressAccess(userOp.Sender, netWork); err != nil { - return err - } else if !ok { - return xerrors.Errorf("sender address not exist in [%s] network", netWork) - } - //check balance - } - if userOp.InitCode == "" { - return xerrors.Errorf("initCode can not be empty if sender is empty") + + if ok, err := chain_service.CheckContractAddressAccess(userOp.Sender, netWork); err != nil { + return err + } else if !ok { + return xerrors.Errorf("sender address not exist in [%s] network", netWork) } + //check balance + + //if userOp.InitCode == "" { + // return xerrors.Errorf("initCode can not be empty if sender is empty") + //} if err := checkInitCode(userOp.InitCode, netWork); err != nil { } return nil } -func checkInitCode(initCode string, network types.Network) error { - initCodeByte, err := hex.DecodeString(initCode) - if err != nil { - return xerrors.Errorf("initCode is not hex string %s", initCode) - } - if len(initCodeByte) < 20 { - return xerrors.Errorf("initCode is not valid %s", initCode) - } - factoryAddress := common.BytesToAddress(initCodeByte[:20]) - if ok, err := chain_service.CheckContractAddressAccess(factoryAddress.String(), network); err != nil { +func checkInitCode(initCode []byte, network types.Network) error { + + factoryAddress := common.BytesToAddress(initCode[:20]) + if ok, err := chain_service.CheckContractAddressAccess(factoryAddress, network); err != nil { return err } else if !ok { return xerrors.Errorf("sender address not exist in [%s] network", network) From 9ffba1d5cc79ed6e76b696c5ff0837831b956bed Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 12 Mar 2024 20:00:46 +0800 Subject: [PATCH 06/47] add userop gasCompute --- common/model/api_response.go | 16 +++--- common/model/gas_price.go | 12 +++++ common/model/user_operation.go | 5 +- service/chain_service/chain_service.go | 55 +++++++++++++++++--- service/chain_service/chain_test.go | 5 ++ service/gas_service/gas_computor.go | 39 +++++++++----- service/validator_service/basic_validator.go | 2 +- 7 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 common/model/gas_price.go 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") } From 94194346e689d929597636f904f4a65eb85a867d Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 12 Mar 2024 22:03:34 +0800 Subject: [PATCH 07/47] add paymaster_generator impl change swagger --- docs/docs.go | 52 ++----------------- docs/swagger.json | 52 ++----------------- docs/swagger.yaml | 39 ++------------ go.mod | 6 +-- go.sum | 2 - .../erc20_paymaster_generator.go | 12 +++-- .../paymaster_generator.go | 28 ++++++++-- .../vertifying_paymaster_generator.go | 23 ++++++-- service/operator/try_pay_user_op_execute.go | 28 ++++++---- 9 files changed, 85 insertions(+), 157 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index a7837d6a..a5400acb 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -172,7 +172,7 @@ const docTemplate = `{ "type": "string" }, "force_network": { - "$ref": "#/definitions/types.NetWork" + "$ref": "#/definitions/types.Network" }, "force_strategy_id": { "type": "string" @@ -181,56 +181,12 @@ const docTemplate = `{ "type": "string" }, "user_operation": { - "$ref": "#/definitions/model.UserOperationItem" + "type": "object", + "additionalProperties": {} } } }, - "model.UserOperationItem": { - "type": "object", - "required": [ - "call_data", - "call_gas_limit", - "max_fee_per_gas", - "max_priority_fee_per_gas", - "nonce", - "per_verification_gas", - "sender", - "verification_gas_list" - ], - "properties": { - "call_data": { - "type": "string" - }, - "call_gas_limit": { - "type": "string" - }, - "init_code": { - "type": "string" - }, - "max_fee_per_gas": { - "type": "string" - }, - "max_priority_fee_per_gas": { - "type": "string" - }, - "nonce": { - "type": "string" - }, - "per_verification_gas": { - "type": "string" - }, - "sender": { - "type": "string" - }, - "signature": { - "type": "string" - }, - "verification_gas_list": { - "type": "string" - } - } - }, - "types.NetWork": { + "types.Network": { "type": "string", "enum": [ "ethereum", diff --git a/docs/swagger.json b/docs/swagger.json index 1f1f8b81..87f9ac7c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -161,7 +161,7 @@ "type": "string" }, "force_network": { - "$ref": "#/definitions/types.NetWork" + "$ref": "#/definitions/types.Network" }, "force_strategy_id": { "type": "string" @@ -170,56 +170,12 @@ "type": "string" }, "user_operation": { - "$ref": "#/definitions/model.UserOperationItem" + "type": "object", + "additionalProperties": {} } } }, - "model.UserOperationItem": { - "type": "object", - "required": [ - "call_data", - "call_gas_limit", - "max_fee_per_gas", - "max_priority_fee_per_gas", - "nonce", - "per_verification_gas", - "sender", - "verification_gas_list" - ], - "properties": { - "call_data": { - "type": "string" - }, - "call_gas_limit": { - "type": "string" - }, - "init_code": { - "type": "string" - }, - "max_fee_per_gas": { - "type": "string" - }, - "max_priority_fee_per_gas": { - "type": "string" - }, - "nonce": { - "type": "string" - }, - "per_verification_gas": { - "type": "string" - }, - "sender": { - "type": "string" - }, - "signature": { - "type": "string" - }, - "verification_gas_list": { - "type": "string" - } - } - }, - "types.NetWork": { + "types.Network": { "type": "string", "enum": [ "ethereum", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b53d21a3..ed1f05be 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -10,47 +10,16 @@ definitions: force_entrypoint_address: type: string force_network: - $ref: '#/definitions/types.NetWork' + $ref: '#/definitions/types.Network' force_strategy_id: type: string force_token: type: string user_operation: - $ref: '#/definitions/model.UserOperationItem' + additionalProperties: {} + type: object type: object - model.UserOperationItem: - properties: - call_data: - type: string - call_gas_limit: - type: string - init_code: - type: string - max_fee_per_gas: - type: string - max_priority_fee_per_gas: - type: string - nonce: - type: string - per_verification_gas: - type: string - sender: - type: string - signature: - type: string - verification_gas_list: - type: string - required: - - call_data - - call_gas_limit - - max_fee_per_gas - - max_priority_fee_per_gas - - nonce - - per_verification_gas - - sender - - verification_gas_list - type: object - types.NetWork: + types.Network: enum: - ethereum - sepolia diff --git a/go.mod b/go.mod index 86443055..6549cf59 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,9 @@ require ( github.com/ethereum/go-ethereum v1.13.14 github.com/gin-contrib/cors v1.5.0 github.com/gin-gonic/gin v1.9.1 + github.com/go-playground/validator/v10 v10.18.0 + github.com/holiman/uint256 v1.2.4 + github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.4 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 @@ -41,18 +44,15 @@ require ( github.com/go-openapi/swag v0.22.9 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.18.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/holiman/uint256 v1.2.4 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index 3b06b2bf..944906a8 100644 --- a/go.sum +++ b/go.sum @@ -167,8 +167,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= diff --git a/paymaster_data_generator/erc20_paymaster_generator.go b/paymaster_data_generator/erc20_paymaster_generator.go index b055c1c1..54bd670f 100644 --- a/paymaster_data_generator/erc20_paymaster_generator.go +++ b/paymaster_data_generator/erc20_paymaster_generator.go @@ -1,11 +1,17 @@ package paymaster_data_generator -import "AAStarCommunity/EthPaymaster_BackService/common/model" +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" + "encoding/hex" +) type Erc20PaymasterGenerator struct { } -func (e Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { +func (e *Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { //ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount - return "0x", nil + res := "0x" + string(types.PayTypeERC20) + strategy.PayMasterAddress + gasResponse.TokenCost + //TODO implement me + return hex.DecodeString(res) } diff --git a/paymaster_data_generator/paymaster_generator.go b/paymaster_data_generator/paymaster_generator.go index b6f1fdcb..e50b6c16 100644 --- a/paymaster_data_generator/paymaster_generator.go +++ b/paymaster_data_generator/paymaster_generator.go @@ -1,7 +1,29 @@ package paymaster_data_generator -import "AAStarCommunity/EthPaymaster_BackService/common/model" +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" +) -type PaymasterGenerator interface { - GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) +var ( + PaymasterDataGeneratorFactories map[types.PayType]PaymasterDataGenerator +) + +func init() { + PaymasterDataGeneratorFactories = make(map[types.PayType]PaymasterDataGenerator) + PaymasterDataGeneratorFactories[types.PayTypeVerifying] = &VerifyingPaymasterGenerator{} + PaymasterDataGeneratorFactories[types.PayTypeERC20] = &Erc20PaymasterGenerator{} +} + +type PaymasterDataGenerator interface { + GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) +} + +func GetPaymasterDataGenerator(payType types.PayType) PaymasterDataGenerator { + + paymasterDataGenerator, ok := PaymasterDataGeneratorFactories[payType] + if !ok { + return nil + } + return paymasterDataGenerator } diff --git a/paymaster_data_generator/vertifying_paymaster_generator.go b/paymaster_data_generator/vertifying_paymaster_generator.go index 7709f90f..b0a1af21 100644 --- a/paymaster_data_generator/vertifying_paymaster_generator.go +++ b/paymaster_data_generator/vertifying_paymaster_generator.go @@ -1,12 +1,27 @@ package paymaster_data_generator -import "AAStarCommunity/EthPaymaster_BackService/common/model" +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" + "golang.org/x/xerrors" +) type VerifyingPaymasterGenerator struct { } -func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { +func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature - return "0x", nil - + //TODO implement + signature, ok := extra["signature"] + if !ok { + return nil, xerrors.Errorf("signature not found") + } + res := "0x" + string(types.PayTypeVerifying) + strategy.PayMasterAddress + "" + signature.(string) + return []byte(res), nil } + +//func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { +// //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature +// return "0x", nil +// +//} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 08fb56b0..0213635f 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -5,6 +5,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/conf" + "AAStarCommunity/EthPaymaster_BackService/paymaster_data_generator" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "AAStarCommunity/EthPaymaster_BackService/service/gas_service" @@ -61,10 +62,16 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO if payError != nil { return nil, payError } - paymasterAndData := getPayMasterAndData(strategy, userOp) + paymasterSignature := getPayMasterSignature(strategy, userOp) + + var paymasterAndData []byte + if paymasterAndDataRes, err := getPayMasterAndData(strategy, userOp, gasResponse, paymasterSignature); err != nil { + return nil, err + } else { + paymasterAndData = paymasterAndDataRes + } userOp.PaymasterAndData = paymasterAndData //validatePaymasterUserOp - paymasterSignature := getPayMasterSignature(strategy, userOp) var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, EntryPointAddress: strategy.EntryPointAddress, @@ -117,15 +124,14 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } -func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation) []byte { - //TODO - if strategy.PayType == types.PayTypeERC20 { - return []byte("ERC20") - } - if strategy.PayType == types.PayTypeVerifying { - return []byte("Verifying") - } - return []byte("ETH") +func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, paymasterSign string) ([]byte, error) { + paymasterDataGenerator := paymaster_data_generator.GetPaymasterDataGenerator(strategy.PayType) + if paymasterDataGenerator == nil { + return nil, xerrors.Errorf("Not Support PayType: [%w]", strategy.PayType) + } + extra := make(map[string]any) + extra["signature"] = paymasterSign + return paymasterDataGenerator.GeneratePayMaster(strategy, userOp, gasResponse, extra) } func strategyGenerate(request *model.TryPayUserOpRequest) (*model.Strategy, error) { From 38ea028123a8eb554b78520d87e98e7220f19b37 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 12 Mar 2024 22:46:11 +0800 Subject: [PATCH 08/47] update --- common/model/api_response.go | 2 +- common/types/chain.go | 6 ++++-- .../vertifying_paymaster_generator.go | 7 ------- service/chain_service/chain_config.go | 10 ++++++---- service/gas_service/gas_computor.go | 8 +++++++- service/operator/try_pay_user_op_execute.go | 2 +- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/common/model/api_response.go b/common/model/api_response.go index 76a17877..ef04409b 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -40,5 +40,5 @@ type EntrypointDomain struct { } type GetSupportStrategyResponse struct { - Strategies []Strategy `json:"strategies"` + Strategies *[]Strategy `json:"strategies"` } diff --git a/common/types/chain.go b/common/types/chain.go index b4f0c507..0eebad6d 100644 --- a/common/types/chain.go +++ b/common/types/chain.go @@ -1,8 +1,9 @@ package types type NetworkInfo struct { - Name string `json:"main_net_name"` - RpcUrl string `json:"main_net_rpc_url"` + Name string `json:"main_net_name"` + RpcUrl string `json:"main_net_rpc_url"` + GasToken TokenType `json:"gas_token"` } //type Chain string @@ -19,6 +20,7 @@ const ( Ethereum Network = "ethereum" Sepolia Network = "sepolia" Arbitrum Network = "arbitrum" + ArbTest Network = "arb-sepolia" ) var TestNetWork = map[Network]bool{} diff --git a/paymaster_data_generator/vertifying_paymaster_generator.go b/paymaster_data_generator/vertifying_paymaster_generator.go index b0a1af21..cf9ed963 100644 --- a/paymaster_data_generator/vertifying_paymaster_generator.go +++ b/paymaster_data_generator/vertifying_paymaster_generator.go @@ -11,7 +11,6 @@ type VerifyingPaymasterGenerator struct { func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature - //TODO implement signature, ok := extra["signature"] if !ok { return nil, xerrors.Errorf("signature not found") @@ -19,9 +18,3 @@ func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, res := "0x" + string(types.PayTypeVerifying) + strategy.PayMasterAddress + "" + signature.(string) return []byte(res), nil } - -//func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation) (string, error) { -// //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature -// return "0x", nil -// -//} diff --git a/service/chain_service/chain_config.go b/service/chain_service/chain_config.go index 7171319e..7144193a 100644 --- a/service/chain_service/chain_config.go +++ b/service/chain_service/chain_config.go @@ -16,12 +16,14 @@ func ConfigInit() { //TODO api key secret store NetworkInfoMap = map[types.Network]*types.NetworkInfo{ types.Ethereum: { - Name: "ethereum", - RpcUrl: "https://eth-mainnet.g.alchemy.com/v2/bIZQS43-rJMgv2_SiHqfVvXa-Z1UGoGt", + Name: "ethereum", + RpcUrl: "https://eth-mainnet.g.alchemy.com/v2/bIZQS43-rJMgv2_SiHqfVvXa-Z1UGoGt", + GasToken: types.ETH, }, types.Sepolia: { - Name: "sepolia", - RpcUrl: "https://eth-sepolia.g.alchemy.com/v2/wKeLycGxgYRykgf0aGfcpEkUtqyLQg4v", + Name: "sepolia", + RpcUrl: "https://eth-sepolia.g.alchemy.com/v2/wKeLycGxgYRykgf0aGfcpEkUtqyLQg4v", + GasToken: types.ETH, }, } } diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index 36dca222..2f4eaf44 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -2,6 +2,7 @@ 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" @@ -51,10 +52,15 @@ func GetTokenCost(maxFee big.Int, userOp *model.UserOperation, strategy model.St return "0.0001" } -func ValidateGas(userOp *model.UserOperation, gasComputeResponse *model.ComputeGasResponse) error { +func ValidateGas(userOp *model.UserOperation, gasComputeResponse *model.ComputeGasResponse, strategy *model.Strategy) 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. + if strategy.PayType == types.PayTypeERC20 { + //TODO check address balance + } else if strategy.PayType == types.PayTypeVerifying { + //TODO check paymaster balance + } return nil } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 0213635f..4e968393 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -53,7 +53,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO } //validate gas - if err := gas_service.ValidateGas(userOp, gasResponse); err != nil { + if err := gas_service.ValidateGas(userOp, gasResponse, strategy); err != nil { return nil, err } From 23f1117f7a4e979b45d093032853b996cf1bf9ef Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 13 Mar 2024 20:04:12 +0800 Subject: [PATCH 09/47] update --- common/model/user_operation.go | 33 +++++++++++++++++++++++++++++++++ common/utils/util_test.go | 3 ++- docs/docs.go | 6 ++++-- docs/swagger.json | 6 ++++-- docs/swagger.yaml | 2 ++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 827b7b99..cf79132d 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -3,10 +3,17 @@ package model import ( "encoding/hex" "github.com/ethereum/go-ethereum/common" + "github.com/go-playground/validator/v10" "github.com/mitchellh/mapstructure" "golang.org/x/xerrors" "math/big" "reflect" + "sync" +) + +var ( + validate = validator.New() + onlyOnce = sync.Once{} ) // UserOperation entrypoint v0.0.6 @@ -58,10 +65,36 @@ func NewUserOp(userOp *map[string]any) (*UserOperation, error) { if err := decoder.Decode(userOp); err != nil { return nil, xerrors.Errorf("data [%w] convert failed: [%w]", userOp, err) } + onlyOnce.Do(func() { + validate.RegisterCustomTypeFunc(validateAddressType, common.Address{}) + validate.RegisterCustomTypeFunc(validateBigIntType, big.Int{}) + }) + err = validate.Struct(result) + if err != nil { + return nil, err + } return &result, nil } +func validateAddressType(field reflect.Value) interface{} { + value, ok := field.Interface().(common.Address) + if !ok || value == common.HexToAddress("0x") { + return nil + } + + return field +} + +func validateBigIntType(field reflect.Value) interface{} { + value, ok := field.Interface().(big.Int) + if !ok || value.Cmp(big.NewInt(0)) == -1 { + return nil + } + + return field +} + func exactFieldMatch(mapKey, fieldName string) bool { return mapKey == fieldName } diff --git a/common/utils/util_test.go b/common/utils/util_test.go index 0beff9be..b65aa0e5 100644 --- a/common/utils/util_test.go +++ b/common/utils/util_test.go @@ -31,10 +31,11 @@ func TestSignUserOp(t *testing.T) { } signByte, err := SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) assert.NoError(t, err) + len := len(signByte) + fmt.Printf("signByte len: %d\n", len) fmt.Printf("signByte: %x\n", signByte) singature := hex.EncodeToString(signByte) fmt.Printf("singature: %s\n", singature) - } func TestNewUserOp(t *testing.T) { userOp, newErr := model.NewUserOp(GenerateMockUserOperation()) diff --git a/docs/docs.go b/docs/docs.go index a5400acb..5128b19b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -191,12 +191,14 @@ const docTemplate = `{ "enum": [ "ethereum", "sepolia", - "arbitrum" + "arbitrum", + "arb-sepolia" ], "x-enum-varnames": [ "Ethereum", "Sepolia", - "Arbitrum" + "Arbitrum", + "ArbTest" ] } }, diff --git a/docs/swagger.json b/docs/swagger.json index 87f9ac7c..a4c6fd73 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -180,12 +180,14 @@ "enum": [ "ethereum", "sepolia", - "arbitrum" + "arbitrum", + "arb-sepolia" ], "x-enum-varnames": [ "Ethereum", "Sepolia", - "Arbitrum" + "Arbitrum", + "ArbTest" ] } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ed1f05be..830a0db3 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -24,11 +24,13 @@ definitions: - ethereum - sepolia - arbitrum + - arb-sepolia type: string x-enum-varnames: - Ethereum - Sepolia - Arbitrum + - ArbTest info: contact: name: AAStar Support From fa2f16182c033d1740c63c94926da9c6e0f89a13 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 13 Mar 2024 21:24:57 +0800 Subject: [PATCH 10/47] support get token price --- common/model/user_operation.go | 16 +++++------ common/types/token.go | 1 + common/utils/price_util.go | 50 +++++++++++++++++++++++++++++++++ common/utils/price_util_test.go | 17 +++++++++++ 4 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 common/utils/price_util.go create mode 100644 common/utils/price_util_test.go diff --git a/common/model/user_operation.go b/common/model/user_operation.go index cf79132d..6c871eb7 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -23,15 +23,15 @@ var ( 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"` - 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"` + InitCode []byte `json:"init_code" mapstructure:"init_code" ` + CallData []byte `json:"call_data" mapstructure:"call_data" binding:"required"` + CallGasLimit *big.Int `json:"call_gas_limit" mapstructure:"call_gas_limit" binding:"required"` + VerificationGasLimit *big.Int `json:"verification_gas_limit" mapstructure:"verification_gas_limit" binding:"required"` + PreVerificationGas *big.Int `json:"pre_verification_gas" mapstructure:"pre_verification_gas" binding:"required"` + MaxFeePerGas *big.Int `json:"max_fee_per_gas" mapstructure:"max_fee_per_gas" binding:"required"` + MaxPriorityFeePerGas *big.Int `json:"max_priority_fee_per_gas" mapstructure:"max_priority_fee_per_gas" binding:"required"` Signature []byte `json:"signature" mapstructure:"signature" binding:"required"` - PaymasterAndData []byte `json:"paymasterAndData" mapstructure:"paymasterAndData"` + PaymasterAndData []byte `json:"paymaster_and_data" mapstructure:"paymaster_and_data"` } // PackUserOperation entrypoint v0.0.67 diff --git a/common/types/token.go b/common/types/token.go index 7aaf6b13..c53b4445 100644 --- a/common/types/token.go +++ b/common/types/token.go @@ -4,6 +4,7 @@ type TokenType string const ( USDT TokenType = "usdt" + USDC TokenType = "usdc" ETH TokenType = "eth" OP TokenType = "op" ) diff --git a/common/utils/price_util.go b/common/utils/price_util.go new file mode 100644 index 00000000..2d42c857 --- /dev/null +++ b/common/utils/price_util.go @@ -0,0 +1,50 @@ +package utils + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/types" + "golang.org/x/xerrors" + "io" + "net/http" + "strconv" + "strings" +) + +var ( + URLMap = map[types.TokenType]string{} +) + +type Price struct { +} + +func init() { + URLMap = make(map[types.TokenType]string) + URLMap[types.ETH] = "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" + URLMap[types.OP] = "https://api.coingecko.com/api/v3/simple/price?ids=optimism&vs_currencies=usd" +} + +func GetPriceUsd(tokenType types.TokenType) (float64, error) { + url, ok := URLMap[tokenType] + if !ok { + return 0, xerrors.Errorf("token type [%w] not found", tokenType) + } + req, _ := http.NewRequest("GET", url, nil) + + req.Header.Add("x-cg-demo-api-key", "CG-ioE6p8cmmSFBFwJnKECCbZ7U\t") + + res, _ := http.DefaultClient.Do(req) + + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + bodystr := string(body) + strarr := strings.Split(bodystr, ":") + usdstr := strings.TrimRight(strarr[2], "}}") + return strconv.ParseFloat(usdstr, 64) +} +func GetToken(fromToken types.TokenType, toToken types.TokenType) (float64, error) { + if toToken == types.USDT { + return GetPriceUsd(fromToken) + } + formTokenPrice, _ := GetPriceUsd(fromToken) + toTokenPrice, _ := GetPriceUsd(toToken) + return formTokenPrice / toTokenPrice, nil +} diff --git a/common/utils/price_util_test.go b/common/utils/price_util_test.go new file mode 100644 index 00000000..f2e11b61 --- /dev/null +++ b/common/utils/price_util_test.go @@ -0,0 +1,17 @@ +package utils + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/types" + "fmt" + "testing" +) + +func TestGetPriceUsd(t *testing.T) { + price, _ := GetPriceUsd(types.OP) + fmt.Println(price) +} + +func TestGetToken(t *testing.T) { + price, _ := GetToken(types.ETH, types.OP) + fmt.Println(price) +} From e53c549cc72c52d833ba63075e72dcaaeabeeb8a Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 13 Mar 2024 21:29:57 +0800 Subject: [PATCH 11/47] fix debug --- service/chain_service/chain_test.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index ca88e5c3..66beb731 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -16,17 +16,9 @@ func TestCheckContractAddressAccess(t *testing.T) { assert.True(t, res) } func TestGetGasPrice(t *testing.T) { - priceWei, gasPriceInGwei, gasPriceInEtherStr, _ := GetGasPrice(types.Ethereum) - priceWeiInt := priceWei.Uint64() - 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()) + gasprice, _ := GetGasPrice(types.Ethereum) + fmt.Printf("gasprice %d\n", gasprice.MaxBasePriceWei.Uint64()) - priorFee, priorFeeIGwei := GetPriorityFee(types.Ethereum) - fmt.Printf("priorFee %d\n", priorFee.Uint64()) - fmt.Printf("priorFeeIGwei %f\n", priorFeeIGwei) } func TestGethClient(t *testing.T) { From ab09981fe7a7bd5b99a598b2de369c9c0fee5a4b Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 13 Mar 2024 23:17:21 +0800 Subject: [PATCH 12/47] fix debug --- common/model/api_response.go | 1 + common/model/gas_price.go | 8 ++--- common/model/user_operation.go | 1 - common/utils/price_util.go | 1 + service/chain_service/chain_service.go | 49 +++++++++++++++++++++----- service/chain_service/chain_test.go | 3 ++ service/gas_service/gas_computor.go | 34 ++++++++++++++---- 7 files changed, 78 insertions(+), 19 deletions(-) diff --git a/common/model/api_response.go b/common/model/api_response.go index ef04409b..072e21e5 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -20,6 +20,7 @@ type ComputeGasResponse struct { TokenCost string `json:"token_cost"` Network types.Network `json:"network"` Token types.TokenType `json:"token"` + TokenCount string `json:"token_count"` UsdCost string `json:"usd_cost"` BlobEnable bool `json:"blob_enable"` MaxFee big.Int `json:"max_fee"` diff --git a/common/model/gas_price.go b/common/model/gas_price.go index 27081a95..1b384103 100644 --- a/common/model/gas_price.go +++ b/common/model/gas_price.go @@ -4,9 +4,9 @@ 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"` + MaxBasePriceGwei float64 `json:"max_base_price_gwei"` + MaxBasePriceEther *big.Float `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"` + MaxPriorityPriceGwei float64 `json:"max_priority_price_gwei"` + MaxPriorityPriceEther *big.Float `json:"max_priority_price_ether"` } diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 6c871eb7..9c63bc2f 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -49,7 +49,6 @@ type PackUserOperation struct { } func NewUserOp(userOp *map[string]any) (*UserOperation, error) { - var result UserOperation // Convert map to struct decodeConfig := &mapstructure.DecoderConfig{ diff --git a/common/utils/price_util.go b/common/utils/price_util.go index 2d42c857..a385b026 100644 --- a/common/utils/price_util.go +++ b/common/utils/price_util.go @@ -46,5 +46,6 @@ func GetToken(fromToken types.TokenType, toToken types.TokenType) (float64, erro } formTokenPrice, _ := GetPriceUsd(fromToken) toTokenPrice, _ := GetPriceUsd(toToken) + return formTokenPrice / toTokenPrice, nil } diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index 287fd4e3..889720d5 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -5,10 +5,12 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "context" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "golang.org/x/xerrors" "math/big" + "strings" ) var GweiFactor = new(big.Float).SetInt(big.NewInt(1e9)) @@ -55,19 +57,17 @@ func GetGasPrice(chain types.Network) (*model.GasPrice, error) { gasPriceInGwei.Quo(gasPriceInGwei, GweiFactor) gasPriceInEther := new(big.Float).SetInt(priceWei) gasPriceInEther.Quo(gasPriceInEther, EthWeiFactor) - gasPriceInEtherStr := gasPriceInEther.Text('f', 18) - result.MaxBasePriceGwei = gasPriceInGwei - result.MaxBasePriceEther = &gasPriceInEtherStr + gasPriceInGweiFloat, _ := gasPriceInGwei.Float64() + result.MaxBasePriceGwei = gasPriceInGweiFloat + result.MaxBasePriceEther = gasPriceInEther 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 + priorityPriceInGweiFloat, _ := priorityPriceInGwei.Float64() + result.MaxPriorityPriceGwei = priorityPriceInGweiFloat + result.MaxPriorityPriceEther = gasPriceInEther return &result, nil } @@ -103,3 +103,36 @@ func EstimateGasLimitAndCost(chain types.Network, msg ethereum.CallMsg) (uint64, } return client.EstimateGas(context.Background(), msg) } +func GetAddressTokenBalance(network types.Network, address common.Address, token types.TokenType) ([]interface{}, error) { + client, exist := EthCompatibleNetWorkClientMap[network] + if !exist { + return nil, xerrors.Errorf("chain Client [%s] not exist", network) + } + client.BalanceAt(context.Background(), address, nil) + usdtContractAddress := common.HexToAddress("0xdac17f958d2ee523a2206206994597c13d831ec7") + //address := common.HexToAddress("0xDf7093eF81fa23415bb703A685c6331584D30177") + const bananceABI = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]` + usdtABI, jsonErr := abi.JSON(strings.NewReader(bananceABI)) + if jsonErr != nil { + return nil, jsonErr + } + data, backErr := usdtABI.Pack("balanceOf", address) + if backErr != nil { + return nil, backErr + + } + //usdtInstance, err := ethclient.NewContract(usdtContractAddress, usdtAbi, client) + result, callErr := client.CallContract(context.Background(), ethereum.CallMsg{ + To: &usdtContractAddress, + Data: data, + }, nil) + if callErr != nil { + return nil, callErr + } + var balanceResult, unpackErr = usdtABI.Unpack("balanceOf", result) + if unpackErr != nil { + return nil, unpackErr + } + //TODO get token balance + return balanceResult, nil +} diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index 66beb731..bdc5dbc5 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -19,6 +19,9 @@ func TestGetGasPrice(t *testing.T) { gasprice, _ := GetGasPrice(types.Ethereum) fmt.Printf("gasprice %d\n", gasprice.MaxBasePriceWei.Uint64()) + fmt.Printf("gaspricegwei %f\n", gasprice.MaxBasePriceGwei) + fmt.Printf("gaspriceeth %s\n", gasprice.MaxBasePriceEther.String()) + } func TestGethClient(t *testing.T) { diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index 2f4eaf44..ac1d9e56 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -3,6 +3,7 @@ package gas_service import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -31,13 +32,21 @@ func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.C maxGasLimit := big.NewInt(0).Add(userOp.CallGasLimit, userOp.VerificationGasLimit) maxGasLimit = maxGasLimit.Add(maxGasLimit, payMasterPostGasLimit) - maxFee := new(big.Int).Mul(maxGasLimit, gasPrice.MaxBasePriceWei) + maxFeePriceInEther := new(big.Float).SetInt(maxFee) + maxFeePriceInEther.Quo(maxFeePriceInEther, chain_service.EthWeiFactor) + tokenCost, _ := getTokenCost(strategy, maxFeePriceInEther) + if strategy.PayType == types.PayTypeERC20 { + //TODO get ERC20 balance + if err := validateErc20Paymaster(tokenCost, strategy); err != nil { + return nil, err + } + } + // TODO get PaymasterCallGasLimit - tokenCost := GetTokenCost(*maxFee, userOp, *strategy) return &model.ComputeGasResponse{ GasInfo: gasPrice, - TokenCost: tokenCost, + TokenCost: tokenCost.Text('f', 18), Network: strategy.NetWork, Token: strategy.Token, UsdCost: "0.4", @@ -45,11 +54,24 @@ func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.C MaxFee: *maxFee, }, nil } -func GetPayMasterGasLimit() *big.Int { +func validateErc20Paymaster(tokenCost *big.Float, strategy *model.Strategy) error { + //useToken := strategy.Token + //// get User address balance + //TODO return nil } -func GetTokenCost(maxFee big.Int, userOp *model.UserOperation, strategy model.Strategy) string { - return "0.0001" +func getTokenCost(strategy *model.Strategy, tokenCount *big.Float) (*big.Float, error) { + formTokenType := chain_service.NetworkInfoMap[strategy.NetWork].GasToken + toTokenType := strategy.Token + toTokenPrice, err := utils.GetToken(formTokenType, toTokenType) + if err != nil { + return nil, err + } + tokenCost := new(big.Float).Mul(tokenCount, big.NewFloat(toTokenPrice)) + return tokenCost, nil +} +func GetPayMasterGasLimit() *big.Int { + return nil } func ValidateGas(userOp *model.UserOperation, gasComputeResponse *model.ComputeGasResponse, strategy *model.Strategy) error { From 00ebc7db221fb136acf1e279af0a32510daac78f Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 14 Mar 2024 13:38:53 +0800 Subject: [PATCH 13/47] optimize gas compute --- common/model/api_response.go | 4 +- common/types/token.go | 13 +++++ common/utils/util.go | 22 +++---- .../erc20_paymaster_generator.go | 17 ------ .../paymaster_generator.go | 29 ---------- .../vertifying_paymaster_generator.go | 20 ------- .../erc20_paymaster_generator.go | 34 +++++++++++ paymaster_pay_type/paymaster_generator.go | 29 ++++++++++ .../vertifying_paymaster_generator.go | 39 +++++++++++++ service/chain_service/chain_service.go | 58 +++++++++++++------ service/chain_service/chain_test.go | 6 ++ .../dashboard_service/dashboard_service.go | 4 ++ service/gas_service/gas_computor.go | 45 ++++++-------- service/operator/try_pay_user_op_execute.go | 9 +-- 14 files changed, 203 insertions(+), 126 deletions(-) delete mode 100644 paymaster_data_generator/erc20_paymaster_generator.go delete mode 100644 paymaster_data_generator/paymaster_generator.go delete mode 100644 paymaster_data_generator/vertifying_paymaster_generator.go create mode 100644 paymaster_pay_type/erc20_paymaster_generator.go create mode 100644 paymaster_pay_type/paymaster_generator.go create mode 100644 paymaster_pay_type/vertifying_paymaster_generator.go diff --git a/common/model/api_response.go b/common/model/api_response.go index 072e21e5..b1293e8c 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -17,11 +17,11 @@ type TryPayUserOpResponse struct { type ComputeGasResponse struct { GasInfo *GasPrice `json:"gas_info"` - TokenCost string `json:"token_cost"` + TokenCost *big.Float `json:"token_cost"` Network types.Network `json:"network"` Token types.TokenType `json:"token"` TokenCount string `json:"token_count"` - UsdCost string `json:"usd_cost"` + UsdCost float64 `json:"usd_cost"` BlobEnable bool `json:"blob_enable"` MaxFee big.Int `json:"max_fee"` } diff --git a/common/types/token.go b/common/types/token.go index c53b4445..a9694f46 100644 --- a/common/types/token.go +++ b/common/types/token.go @@ -2,6 +2,19 @@ package types type TokenType string +var StableCoinMap map[TokenType]bool + +func init() { + StableCoinMap = map[TokenType]bool{ + USDT: true, + USDC: true, + } +} +func IsStableToken(token TokenType) bool { + _, ok := StableCoinMap[token] + return ok +} + const ( USDT TokenType = "usdt" USDC TokenType = "usdc" diff --git a/common/utils/util.go b/common/utils/util.go index b91dedf7..5ba491c1 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -14,17 +14,17 @@ var HexPattern = regexp.MustCompile(`^0x[a-fA-F\d]*$`) func GenerateMockUserOperation() *map[string]any { //TODO use config var MockUserOpData = map[string]any{ - "sender": "0x4A2FD3215420376DA4eD32853C19E4755deeC4D1", - "nonce": "1", - "initCode": "0xe19e9755942bb0bd0cccce25b1742596b8a8250b3bf2c3e700000000000000000000000078d4f01f56b982a3b03c4e127a5d3afa8ebee6860000000000000000000000008b388a082f370d8ac2e2b3997e9151168bd09ff50000000000000000000000000000000000000000000000000000000000000000", - "callData": "0xb61d27f6000000000000000000000000c206b552ab127608c3f666156c8e03a8471c72df000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", - "callGasLimit": "39837", - "verificationGasLimit": "100000", - "maxFeePerGas": "44020", - "maxPriorityFeePerGas": "1743509478", - "paymasterAndData": "0x", - "preVerificationGas": "44020", - "signature": "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", + "sender": "0x4A2FD3215420376DA4eD32853C19E4755deeC4D1", + "nonce": "1", + "init_code": "0xe19e9755942bb0bd0cccce25b1742596b8a8250b3bf2c3e700000000000000000000000078d4f01f56b982a3b03c4e127a5d3afa8ebee6860000000000000000000000008b388a082f370d8ac2e2b3997e9151168bd09ff50000000000000000000000000000000000000000000000000000000000000000", + "call_data": "0xb61d27f6000000000000000000000000c206b552ab127608c3f666156c8e03a8471c72df000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + "call_gas_limit": "39837", + "verification_gas_limit": "100000", + "max_fee_per_gas": "44020", + "max_priority_fee_per_gas": "1743509478", + "paymaster_and_data": "0x", + "pre_verification_gas": "44020", + "signature": "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", } return &MockUserOpData diff --git a/paymaster_data_generator/erc20_paymaster_generator.go b/paymaster_data_generator/erc20_paymaster_generator.go deleted file mode 100644 index 54bd670f..00000000 --- a/paymaster_data_generator/erc20_paymaster_generator.go +++ /dev/null @@ -1,17 +0,0 @@ -package paymaster_data_generator - -import ( - "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" - "encoding/hex" -) - -type Erc20PaymasterGenerator struct { -} - -func (e *Erc20PaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { - //ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount - res := "0x" + string(types.PayTypeERC20) + strategy.PayMasterAddress + gasResponse.TokenCost - //TODO implement me - return hex.DecodeString(res) -} diff --git a/paymaster_data_generator/paymaster_generator.go b/paymaster_data_generator/paymaster_generator.go deleted file mode 100644 index e50b6c16..00000000 --- a/paymaster_data_generator/paymaster_generator.go +++ /dev/null @@ -1,29 +0,0 @@ -package paymaster_data_generator - -import ( - "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" -) - -var ( - PaymasterDataGeneratorFactories map[types.PayType]PaymasterDataGenerator -) - -func init() { - PaymasterDataGeneratorFactories = make(map[types.PayType]PaymasterDataGenerator) - PaymasterDataGeneratorFactories[types.PayTypeVerifying] = &VerifyingPaymasterGenerator{} - PaymasterDataGeneratorFactories[types.PayTypeERC20] = &Erc20PaymasterGenerator{} -} - -type PaymasterDataGenerator interface { - GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) -} - -func GetPaymasterDataGenerator(payType types.PayType) PaymasterDataGenerator { - - paymasterDataGenerator, ok := PaymasterDataGeneratorFactories[payType] - if !ok { - return nil - } - return paymasterDataGenerator -} diff --git a/paymaster_data_generator/vertifying_paymaster_generator.go b/paymaster_data_generator/vertifying_paymaster_generator.go deleted file mode 100644 index cf9ed963..00000000 --- a/paymaster_data_generator/vertifying_paymaster_generator.go +++ /dev/null @@ -1,20 +0,0 @@ -package paymaster_data_generator - -import ( - "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" - "golang.org/x/xerrors" -) - -type VerifyingPaymasterGenerator struct { -} - -func (v VerifyingPaymasterGenerator) GeneratePayMaster(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { - //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature - signature, ok := extra["signature"] - if !ok { - return nil, xerrors.Errorf("signature not found") - } - res := "0x" + string(types.PayTypeVerifying) + strategy.PayMasterAddress + "" + signature.(string) - return []byte(res), nil -} diff --git a/paymaster_pay_type/erc20_paymaster_generator.go b/paymaster_pay_type/erc20_paymaster_generator.go new file mode 100644 index 00000000..27b9f029 --- /dev/null +++ b/paymaster_pay_type/erc20_paymaster_generator.go @@ -0,0 +1,34 @@ +package paymaster_pay_type + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/service/chain_service" + "encoding/hex" + "golang.org/x/xerrors" + "math/big" +) + +type Erc20PaymasterExecutor struct { +} + +func (e *Erc20PaymasterExecutor) ValidateGas(userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, strategy *model.Strategy) error { + tokenBalance, getTokenBalanceErr := chain_service.GetAddressTokenBalance(strategy.NetWork, userOp.Sender, strategy.Token) + if getTokenBalanceErr != nil { + return getTokenBalanceErr + } + tokenCost := gasResponse.TokenCost + bigFloatValue := new(big.Float).SetFloat64(tokenBalance) + if bigFloatValue.Cmp(tokenCost) < 0 { + return xerrors.Errorf("user Token Not Enough tokenBalance %s < tokenCost %s", tokenBalance, tokenCost) + } + return nil +} + +func (e *Erc20PaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { + //ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount + //tokenCost := gasResponse.TokenCost.Float64() + res := "0x" + string(types.PayTypeERC20) + strategy.PayMasterAddress + //TODO implement me + return hex.DecodeString(res) +} diff --git a/paymaster_pay_type/paymaster_generator.go b/paymaster_pay_type/paymaster_generator.go new file mode 100644 index 00000000..87e491f4 --- /dev/null +++ b/paymaster_pay_type/paymaster_generator.go @@ -0,0 +1,29 @@ +package paymaster_pay_type + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" +) + +var ( + PaymasterDataGeneratorFactories map[types.PayType]PaymasterPayTypeExecutor +) + +func init() { + PaymasterDataGeneratorFactories = make(map[types.PayType]PaymasterPayTypeExecutor) + PaymasterDataGeneratorFactories[types.PayTypeVerifying] = &VerifyingPaymasterExecutor{} + PaymasterDataGeneratorFactories[types.PayTypeERC20] = &Erc20PaymasterExecutor{} +} + +type PaymasterPayTypeExecutor interface { + GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) + ValidateGas(userOp *model.UserOperation, response *model.ComputeGasResponse, strategy *model.Strategy) error +} + +func GetPaymasterDataExecutor(payType types.PayType) PaymasterPayTypeExecutor { + paymasterDataGenerator, ok := PaymasterDataGeneratorFactories[payType] + if !ok { + return nil + } + return paymasterDataGenerator +} diff --git a/paymaster_pay_type/vertifying_paymaster_generator.go b/paymaster_pay_type/vertifying_paymaster_generator.go new file mode 100644 index 00000000..75bb7ee5 --- /dev/null +++ b/paymaster_pay_type/vertifying_paymaster_generator.go @@ -0,0 +1,39 @@ +package paymaster_pay_type + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/service/chain_service" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/xerrors" + "math/big" +) + +type VerifyingPaymasterExecutor struct { +} + +func (v VerifyingPaymasterExecutor) ValidateGas(userOp *model.UserOperation, response *model.ComputeGasResponse, strategy *model.Strategy) error { + //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) + // Paymaster check paymaster balance + + //check EntryPoint paymasterAddress balance + tokenBalance, getTokenBalanceErr := chain_service.GetAddressTokenBalance(strategy.NetWork, common.HexToAddress(strategy.PayMasterAddress), strategy.Token) + if getTokenBalanceErr != nil { + return getTokenBalanceErr + } + tokenBalanceBigFloat := new(big.Float).SetFloat64(tokenBalance) + if tokenBalanceBigFloat.Cmp(response.TokenCost) > 0 { + return xerrors.Errorf("paymaster Token Not Enough tokenBalance %s < tokenCost %s", tokenBalance, response.TokenCost) + } + return nil +} + +func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { + //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature + signature, ok := extra["signature"] + if !ok { + return nil, xerrors.Errorf("signature not found") + } + res := "0x" + string(types.PayTypeVerifying) + strategy.PayMasterAddress + "" + signature.(string) + return []byte(res), nil +} diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index 889720d5..27e0c244 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "golang.org/x/xerrors" + "math" "math/big" "strings" ) @@ -16,6 +17,21 @@ import ( 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)) +const balanceOfAbi = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]` + +var TokenAddressMap map[types.Network]*map[types.TokenType]common.Address + +func init() { + TokenAddressMap = map[types.Network]*map[types.TokenType]common.Address{ + types.Ethereum: { + types.ETH: common.HexToAddress("0xdac17f958d2ee523a2206206994597c13d831ec7"), + }, + types.Sepolia: { + types.USDT: common.HexToAddress("0xaa8e23fb1079ea71e0a56f48a2aa51851d8433d0"), + types.USDC: common.HexToAddress("0x1c7d4b196cb0c7b01d743fbc6116a902379c7238"), + }, + } +} func CheckContractAddressAccess(contract common.Address, chain types.Network) (bool, error) { if chain == "" { return false, xerrors.Errorf("chain can not be empty") @@ -103,36 +119,44 @@ func EstimateGasLimitAndCost(chain types.Network, msg ethereum.CallMsg) (uint64, } return client.EstimateGas(context.Background(), msg) } -func GetAddressTokenBalance(network types.Network, address common.Address, token types.TokenType) ([]interface{}, error) { +func GetAddressTokenBalance(network types.Network, address common.Address, token types.TokenType) (float64, error) { client, exist := EthCompatibleNetWorkClientMap[network] if !exist { - return nil, xerrors.Errorf("chain Client [%s] not exist", network) + return 0, xerrors.Errorf("chain Client [%s] not exist", network) + } + if token == types.ETH { + res, err := client.BalanceAt(context.Background(), address, nil) + if err != nil { + return 0, err + } + bananceV := float64(res.Int64()) * math.Pow(10, -18) + return bananceV, nil } - client.BalanceAt(context.Background(), address, nil) - usdtContractAddress := common.HexToAddress("0xdac17f958d2ee523a2206206994597c13d831ec7") - //address := common.HexToAddress("0xDf7093eF81fa23415bb703A685c6331584D30177") - const bananceABI = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]` - usdtABI, jsonErr := abi.JSON(strings.NewReader(bananceABI)) + + tokenContractAddress := (*TokenAddressMap[network])[token] + usdtABI, jsonErr := abi.JSON(strings.NewReader(balanceOfAbi)) if jsonErr != nil { - return nil, jsonErr + return 0, jsonErr } data, backErr := usdtABI.Pack("balanceOf", address) if backErr != nil { - return nil, backErr - + return 0, backErr } - //usdtInstance, err := ethclient.NewContract(usdtContractAddress, usdtAbi, client) result, callErr := client.CallContract(context.Background(), ethereum.CallMsg{ - To: &usdtContractAddress, + To: &tokenContractAddress, Data: data, }, nil) if callErr != nil { - return nil, callErr + return 0, callErr } - var balanceResult, unpackErr = usdtABI.Unpack("balanceOf", result) + + var balanceResult *big.Int + unpackErr := usdtABI.UnpackIntoInterface(&balanceResult, "balanceOf", result) if unpackErr != nil { - return nil, unpackErr + return 0, unpackErr } - //TODO get token balance - return balanceResult, nil + balanceResultFloat := float64(balanceResult.Int64()) * math.Pow(10, -6) + + return balanceResultFloat, nil + } diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index bdc5dbc5..729d1154 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -30,3 +30,9 @@ func TestGethClient(t *testing.T) { assert.NotEqual(t, 0, num) fmt.Println(num) } +func TestGetAddressTokenBalance(t *testing.T) { + + res, err := GetAddressTokenBalance(types.Sepolia, common.HexToAddress("0xDf7093eF81fa23415bb703A685c6331584D30177"), types.USDC) + assert.NoError(t, err) + fmt.Println(res) +} diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index ba5feec6..f9016f00 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -17,12 +17,16 @@ func init() { EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", NetWork: types.Sepolia, + PayType: types.PayTypeVerifying, + EntryPointTag: types.EntrypointV06, Token: types.USDT, } mockStrategyMap["2"] = &model.Strategy{ Id: "2", EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", + PayType: types.PayTypeERC20, + EntryPointTag: types.EntrypointV06, NetWork: types.Sepolia, Token: types.ETH, } diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index ac1d9e56..0c3ee50e 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -4,6 +4,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/paymaster_pay_type" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -26,40 +27,33 @@ 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() + payMasterPostGasLimit := GetPayMasterGasLimit() maxGasLimit := big.NewInt(0).Add(userOp.CallGasLimit, userOp.VerificationGasLimit) maxGasLimit = maxGasLimit.Add(maxGasLimit, payMasterPostGasLimit) maxFee := new(big.Int).Mul(maxGasLimit, gasPrice.MaxBasePriceWei) maxFeePriceInEther := new(big.Float).SetInt(maxFee) maxFeePriceInEther.Quo(maxFeePriceInEther, chain_service.EthWeiFactor) tokenCost, _ := getTokenCost(strategy, maxFeePriceInEther) - if strategy.PayType == types.PayTypeERC20 { - //TODO get ERC20 balance - if err := validateErc20Paymaster(tokenCost, strategy); err != nil { - return nil, err - } + var usdCost float64 + if types.IsStableToken(strategy.Token) { + usdCost, _ = tokenCost.Float64() + } else { + usdCost, _ = utils.GetPriceUsd(strategy.Token) } // TODO get PaymasterCallGasLimit return &model.ComputeGasResponse{ GasInfo: gasPrice, - TokenCost: tokenCost.Text('f', 18), + TokenCost: tokenCost, Network: strategy.NetWork, Token: strategy.Token, - UsdCost: "0.4", + UsdCost: usdCost, BlobEnable: strategy.Enable4844, MaxFee: *maxFee, }, nil } -func validateErc20Paymaster(tokenCost *big.Float, strategy *model.Strategy) error { - //useToken := strategy.Token - //// get User address balance - //TODO - return nil -} + func getTokenCost(strategy *model.Strategy, tokenCount *big.Float) (*big.Float, error) { formTokenType := chain_service.NetworkInfoMap[strategy.NetWork].GasToken toTokenType := strategy.Token @@ -67,22 +61,21 @@ func getTokenCost(strategy *model.Strategy, tokenCount *big.Float) (*big.Float, if err != nil { return nil, err } + if toTokenPrice == 0 { + return nil, xerrors.Errorf("toTokenPrice can not be 0") + } tokenCost := new(big.Float).Mul(tokenCount, big.NewFloat(toTokenPrice)) return tokenCost, nil } func GetPayMasterGasLimit() *big.Int { - return nil + //TODO + return big.NewInt(0) } func ValidateGas(userOp *model.UserOperation, gasComputeResponse *model.ComputeGasResponse, strategy *model.Strategy) 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. - if strategy.PayType == types.PayTypeERC20 { - //TODO check address balance - } else if strategy.PayType == types.PayTypeVerifying { - //TODO check paymaster balance + paymasterDataExecutor := paymaster_pay_type.GetPaymasterDataExecutor(strategy.PayType) + if paymasterDataExecutor == nil { + return xerrors.Errorf(" %s paymasterDataExecutor not found", strategy.PayType) } - return nil + return paymasterDataExecutor.ValidateGas(userOp, gasComputeResponse, strategy) } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 4e968393..d37afcfa 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -5,7 +5,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/conf" - "AAStarCommunity/EthPaymaster_BackService/paymaster_data_generator" + "AAStarCommunity/EthPaymaster_BackService/paymaster_pay_type" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "AAStarCommunity/EthPaymaster_BackService/service/gas_service" @@ -51,6 +51,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO if gasComputeError != nil { return nil, gasComputeError } + //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. //validate gas if err := gas_service.ValidateGas(userOp, gasResponse, strategy); err != nil { @@ -125,13 +126,13 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation return hex.EncodeToString(signatureBytes) } func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, paymasterSign string) ([]byte, error) { - paymasterDataGenerator := paymaster_data_generator.GetPaymasterDataGenerator(strategy.PayType) - if paymasterDataGenerator == nil { + paymasterDataExecutor := paymaster_pay_type.GetPaymasterDataExecutor(strategy.PayType) + if paymasterDataExecutor == nil { return nil, xerrors.Errorf("Not Support PayType: [%w]", strategy.PayType) } extra := make(map[string]any) extra["signature"] = paymasterSign - return paymasterDataGenerator.GeneratePayMaster(strategy, userOp, gasResponse, extra) + return paymasterDataExecutor.GeneratePayMasterAndData(strategy, userOp, gasResponse, extra) } func strategyGenerate(request *model.TryPayUserOpRequest) (*model.Strategy, error) { From 400eeb820ecb8b9ac86af9c2fdfbcc8bedeefe45 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 14 Mar 2024 14:40:03 +0800 Subject: [PATCH 14/47] update API --- go.sum | 2 ++ service/dashboard_service/dashboard_service.go | 8 ++++---- .../operator/get_support_entry_point_execute.go | 14 ++++++++++++-- .../get_support_entry_point_execute_test.go | 11 +++++++++++ service/operator/get_support_strategy_execute.go | 5 +++-- .../operator/get_support_strategy_execute_test.go | 13 +++++++++++++ 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/go.sum b/go.sum index 944906a8..2be1a2b5 100644 --- a/go.sum +++ b/go.sum @@ -120,6 +120,8 @@ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index f9016f00..708e8ddc 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -7,12 +7,12 @@ import ( ) // TODO just Temp Mock -var mockStrategyMap = map[string]*model.Strategy{} +var MockStrategyMap = map[string]*model.Strategy{} var payMasterSupport = map[string]bool{} var entryPointSupport = map[string]bool{} func init() { - mockStrategyMap["1"] = &model.Strategy{ + MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", @@ -21,7 +21,7 @@ func init() { EntryPointTag: types.EntrypointV06, Token: types.USDT, } - mockStrategyMap["2"] = &model.Strategy{ + MockStrategyMap["2"] = &model.Strategy{ Id: "2", EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", @@ -35,7 +35,7 @@ func init() { payMasterSupport["0x0000000000325602a77416A16136FDafd04b299f"] = true } func GetStrategyById(strategyId string) *model.Strategy { - return mockStrategyMap[strategyId] + return MockStrategyMap[strategyId] } func GetSupportEntryPoint() { diff --git a/service/operator/get_support_entry_point_execute.go b/service/operator/get_support_entry_point_execute.go index 68cc59e2..69d4af70 100644 --- a/service/operator/get_support_entry_point_execute.go +++ b/service/operator/get_support_entry_point_execute.go @@ -1,9 +1,19 @@ package operator -import "AAStarCommunity/EthPaymaster_BackService/common/model" +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/types" +) func GetSupportEntrypointExecute(network string) (*model.GetSupportEntryPointResponse, error) { return &model.GetSupportEntryPointResponse{ - EntrypointDomains: &[]model.EntrypointDomain{}, + EntrypointDomains: &[]model.EntrypointDomain{ + { + Address: "0x0576a174D229E3cFA37253523E645A78A0C91B57", + Desc: "desc", + NetWork: types.Sepolia, + StrategyId: "1", + }, + }, }, nil } diff --git a/service/operator/get_support_entry_point_execute_test.go b/service/operator/get_support_entry_point_execute_test.go index 18b97f2b..e7a7bc07 100644 --- a/service/operator/get_support_entry_point_execute_test.go +++ b/service/operator/get_support_entry_point_execute_test.go @@ -1 +1,12 @@ package operator + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetSupportEntrypointExecute(t *testing.T) { + res, err := GetSupportEntrypointExecute("network") + assert.NoError(t, err) + t.Log(res.EntrypointDomains) +} diff --git a/service/operator/get_support_strategy_execute.go b/service/operator/get_support_strategy_execute.go index 8fe58223..411b8109 100644 --- a/service/operator/get_support_strategy_execute.go +++ b/service/operator/get_support_strategy_execute.go @@ -2,8 +2,9 @@ package operator import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" ) -func GetSupportStrategyExecute(network string) (*model.Result, error) { - return &model.Result{}, nil +func GetSupportStrategyExecute(network string) (map[string]*model.Strategy, error) { + return dashboard_service.MockStrategyMap, nil } diff --git a/service/operator/get_support_strategy_execute_test.go b/service/operator/get_support_strategy_execute_test.go index 18b97f2b..65e2089e 100644 --- a/service/operator/get_support_strategy_execute_test.go +++ b/service/operator/get_support_strategy_execute_test.go @@ -1 +1,14 @@ package operator + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetSupportStrategyExecute(t *testing.T) { + res, err := GetSupportStrategyExecute("network") + assert.NoError(t, err) + assert.NotNil(t, res) + fmt.Println(res["1"]) +} From 22a9b18a34ed44bbcea39716c1003e2b071ca252 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 14 Mar 2024 14:58:28 +0800 Subject: [PATCH 15/47] update API --- .../get_support_entry_point_execute.go | 20 +++++++++---------- .../get_support_entry_point_execute_test.go | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/service/operator/get_support_entry_point_execute.go b/service/operator/get_support_entry_point_execute.go index 69d4af70..ac38f42c 100644 --- a/service/operator/get_support_entry_point_execute.go +++ b/service/operator/get_support_entry_point_execute.go @@ -5,15 +5,13 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" ) -func GetSupportEntrypointExecute(network string) (*model.GetSupportEntryPointResponse, error) { - return &model.GetSupportEntryPointResponse{ - EntrypointDomains: &[]model.EntrypointDomain{ - { - Address: "0x0576a174D229E3cFA37253523E645A78A0C91B57", - Desc: "desc", - NetWork: types.Sepolia, - StrategyId: "1", - }, - }, - }, nil +func GetSupportEntrypointExecute(network string) (*[]model.EntrypointDomain, error) { + entrypoints := make([]model.EntrypointDomain, 0) + entrypoints = append(entrypoints, model.EntrypointDomain{ + Address: "0x0576a174D229E3cFA37253523E645A78A0C91B57", + Desc: "desc", + NetWork: types.Sepolia, + StrategyId: "1", + }) + return &entrypoints, nil } diff --git a/service/operator/get_support_entry_point_execute_test.go b/service/operator/get_support_entry_point_execute_test.go index e7a7bc07..0ffbeed1 100644 --- a/service/operator/get_support_entry_point_execute_test.go +++ b/service/operator/get_support_entry_point_execute_test.go @@ -8,5 +8,5 @@ import ( func TestGetSupportEntrypointExecute(t *testing.T) { res, err := GetSupportEntrypointExecute("network") assert.NoError(t, err) - t.Log(res.EntrypointDomains) + t.Log(res) } From 5d699a33228c7c3321cd7afd024ea316d4208e63 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 14 Mar 2024 15:46:33 +0800 Subject: [PATCH 16/47] update API --- common/utils/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/util.go b/common/utils/util.go index 5ba491c1..1290e435 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -22,9 +22,9 @@ func GenerateMockUserOperation() *map[string]any { "verification_gas_limit": "100000", "max_fee_per_gas": "44020", "max_priority_fee_per_gas": "1743509478", - "paymaster_and_data": "0x", "pre_verification_gas": "44020", "signature": "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", + "paymaster_and_data": "0x", } return &MockUserOpData From 856893652d4fff1776e964ad77e60b92e8718626 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 14 Mar 2024 22:42:28 +0800 Subject: [PATCH 17/47] update API --- common/model/api_response.go | 1 - common/utils/price_util.go | 7 +++++++ .../erc20_paymaster_generator.go | 20 +++++++++++------- paymaster_pay_type/paymaster_generator.go | 2 +- .../vertifying_paymaster_generator.go | 20 +++++++++++------- .../dashboard_service/dashboard_service.go | 6 +++--- service/gas_service/gas_computor.go | 7 ++++++- service/gas_service/gas_computor_test.go | 21 +++++++++++++++++++ service/operator/try_pay_user_op_execute.go | 15 +++++++------ 9 files changed, 71 insertions(+), 28 deletions(-) diff --git a/common/model/api_response.go b/common/model/api_response.go index b1293e8c..d874a736 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -20,7 +20,6 @@ type ComputeGasResponse struct { TokenCost *big.Float `json:"token_cost"` Network types.Network `json:"network"` Token types.TokenType `json:"token"` - TokenCount string `json:"token_count"` UsdCost float64 `json:"usd_cost"` BlobEnable bool `json:"blob_enable"` MaxFee big.Int `json:"max_fee"` diff --git a/common/utils/price_util.go b/common/utils/price_util.go index a385b026..403c7436 100644 --- a/common/utils/price_util.go +++ b/common/utils/price_util.go @@ -23,6 +23,13 @@ func init() { } func GetPriceUsd(tokenType types.TokenType) (float64, error) { + + if types.IsStableToken(tokenType) { + return 1, nil + } + if tokenType == types.ETH { + return 4000, nil + } url, ok := URLMap[tokenType] if !ok { return 0, xerrors.Errorf("token type [%w] not found", tokenType) diff --git a/paymaster_pay_type/erc20_paymaster_generator.go b/paymaster_pay_type/erc20_paymaster_generator.go index 27b9f029..590d1bc0 100644 --- a/paymaster_pay_type/erc20_paymaster_generator.go +++ b/paymaster_pay_type/erc20_paymaster_generator.go @@ -2,7 +2,7 @@ package paymaster_pay_type import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "encoding/hex" "golang.org/x/xerrors" @@ -25,10 +25,16 @@ func (e *Erc20PaymasterExecutor) ValidateGas(userOp *model.UserOperation, gasRes return nil } -func (e *Erc20PaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { - //ERC20:[0-1]pay type,[1-21]paymaster address,[21-53]token Amount - //tokenCost := gasResponse.TokenCost.Float64() - res := "0x" + string(types.PayTypeERC20) + strategy.PayMasterAddress - //TODO implement me - return hex.DecodeString(res) +func (e *Erc20PaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { + validationGas := userOp.VerificationGasLimit.String()[0:16] + postOPGas := userOp.CallGasLimit.String()[0:16] + message := validationGas + postOPGas + string(strategy.PayType) + + signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) + if err != nil { + return "", err + } + signatureStr := hex.EncodeToString(signatureByte) + message = message + signatureStr + return message, nil } diff --git a/paymaster_pay_type/paymaster_generator.go b/paymaster_pay_type/paymaster_generator.go index 87e491f4..89eff3ec 100644 --- a/paymaster_pay_type/paymaster_generator.go +++ b/paymaster_pay_type/paymaster_generator.go @@ -16,7 +16,7 @@ func init() { } type PaymasterPayTypeExecutor interface { - GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) + GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) ValidateGas(userOp *model.UserOperation, response *model.ComputeGasResponse, strategy *model.Strategy) error } diff --git a/paymaster_pay_type/vertifying_paymaster_generator.go b/paymaster_pay_type/vertifying_paymaster_generator.go index 75bb7ee5..5a1f9559 100644 --- a/paymaster_pay_type/vertifying_paymaster_generator.go +++ b/paymaster_pay_type/vertifying_paymaster_generator.go @@ -2,8 +2,9 @@ package paymaster_pay_type import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/types" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" + "encoding/hex" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" "math/big" @@ -28,12 +29,17 @@ func (v VerifyingPaymasterExecutor) ValidateGas(userOp *model.UserOperation, res return nil } -func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) ([]byte, error) { +func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature - signature, ok := extra["signature"] - if !ok { - return nil, xerrors.Errorf("signature not found") + validationGas := userOp.VerificationGasLimit.String()[0:16] + postOPGas := userOp.CallGasLimit.String()[0:16] + message := validationGas + postOPGas + string(strategy.PayType) + + signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) + if err != nil { + return "", err } - res := "0x" + string(types.PayTypeVerifying) + strategy.PayMasterAddress + "" + signature.(string) - return []byte(res), nil + signatureStr := hex.EncodeToString(signatureByte) + message = message + signatureStr + return message, nil } diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 708e8ddc..a820b080 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -15,11 +15,11 @@ func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", - PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", + PayMasterAddress: "0x409646509be42aea79eab370efc2c0ec2e51753b", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, EntryPointTag: types.EntrypointV06, - Token: types.USDT, + Token: types.ETH, } MockStrategyMap["2"] = &model.Strategy{ Id: "2", @@ -28,7 +28,7 @@ func init() { PayType: types.PayTypeERC20, EntryPointTag: types.EntrypointV06, NetWork: types.Sepolia, - Token: types.ETH, + Token: types.USDT, } entryPointSupport["0x0576a174D229E3cFA37253523E645A78A0C91B57"] = true diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index 0c3ee50e..d645f520 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -6,6 +6,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/paymaster_pay_type" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" + "fmt" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" @@ -34,7 +35,11 @@ func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.C maxFee := new(big.Int).Mul(maxGasLimit, gasPrice.MaxBasePriceWei) maxFeePriceInEther := new(big.Float).SetInt(maxFee) maxFeePriceInEther.Quo(maxFeePriceInEther, chain_service.EthWeiFactor) - tokenCost, _ := getTokenCost(strategy, maxFeePriceInEther) + fmt.Printf("maxFeePriceInEther: %f\n", maxFeePriceInEther) + tokenCost, err := getTokenCost(strategy, maxFeePriceInEther) + if err != nil { + return nil, err + } var usdCost float64 if types.IsStableToken(strategy.Token) { usdCost, _ = tokenCost.Float64() diff --git a/service/gas_service/gas_computor_test.go b/service/gas_service/gas_computor_test.go index 27fcf074..852c8b57 100644 --- a/service/gas_service/gas_computor_test.go +++ b/service/gas_service/gas_computor_test.go @@ -1 +1,22 @@ package gas_service + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "encoding/json" + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestComputeGas(t *testing.T) { + userOp, newErr := model.NewUserOp(utils.GenerateMockUserOperation()) + assert.NoError(t, newErr) + strategy := dashboard_service.GetStrategyById("1") + gas, err := ComputeGas(userOp, strategy) + assert.NoError(t, err) + assert.NotNil(t, gas) + jsonBypte, _ := json.Marshal(gas) + fmt.Println(string(jsonBypte)) +} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index d37afcfa..168ddcc0 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -63,15 +63,15 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO if payError != nil { return nil, payError } - paymasterSignature := getPayMasterSignature(strategy, userOp) - var paymasterAndData []byte - if paymasterAndDataRes, err := getPayMasterAndData(strategy, userOp, gasResponse, paymasterSignature); err != nil { + var paymasterAndData string + if paymasterAndDataRes, err := getPayMasterAndData(strategy, userOp, gasResponse); err != nil { return nil, err } else { paymasterAndData = paymasterAndDataRes } - userOp.PaymasterAndData = paymasterAndData + paymasterSignature := getPayMasterSignature(strategy, userOp) + //validatePaymasterUserOp var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, @@ -79,7 +79,7 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO PayMasterAddress: strategy.PayMasterAddress, PayReceipt: payReceipt, PayMasterSignature: paymasterSignature, - PayMasterAndData: utils.EncodeToStringWithPrefix(paymasterAndData), + PayMasterAndData: paymasterAndData, GasInfo: gasResponse, } return result, nil @@ -125,13 +125,12 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } -func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, paymasterSign string) ([]byte, error) { +func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, error) { paymasterDataExecutor := paymaster_pay_type.GetPaymasterDataExecutor(strategy.PayType) if paymasterDataExecutor == nil { - return nil, xerrors.Errorf("Not Support PayType: [%w]", strategy.PayType) + return "", xerrors.Errorf("Not Support PayType: [%w]", strategy.PayType) } extra := make(map[string]any) - extra["signature"] = paymasterSign return paymasterDataExecutor.GeneratePayMasterAndData(strategy, userOp, gasResponse, extra) } From d8467888b47a3d18c5ec95947a1c12e41effb5bf Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 15 Mar 2024 09:34:59 +0800 Subject: [PATCH 18/47] fix bug --- paymaster_pay_type/vertifying_paymaster_generator.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paymaster_pay_type/vertifying_paymaster_generator.go b/paymaster_pay_type/vertifying_paymaster_generator.go index 5a1f9559..d0692047 100644 --- a/paymaster_pay_type/vertifying_paymaster_generator.go +++ b/paymaster_pay_type/vertifying_paymaster_generator.go @@ -31,8 +31,8 @@ func (v VerifyingPaymasterExecutor) ValidateGas(userOp *model.UserOperation, res func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature - validationGas := userOp.VerificationGasLimit.String()[0:16] - postOPGas := userOp.CallGasLimit.String()[0:16] + validationGas := userOp.VerificationGasLimit.String() + postOPGas := userOp.CallGasLimit.String() message := validationGas + postOPGas + string(strategy.PayType) signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) From 4635c644135fb358e89703f5daa20c6be0f2a2cb Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 15 Mar 2024 17:00:11 +0800 Subject: [PATCH 19/47] fix bug --- paymaster_pay_type/erc20_paymaster_generator.go | 9 +++++---- paymaster_pay_type/vertifying_paymaster_generator.go | 6 +++--- service/operator/get_support_entry_point_execute.go | 2 +- service/validator_service/basic_validator.go | 4 +++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/paymaster_pay_type/erc20_paymaster_generator.go b/paymaster_pay_type/erc20_paymaster_generator.go index 590d1bc0..85d3bf70 100644 --- a/paymaster_pay_type/erc20_paymaster_generator.go +++ b/paymaster_pay_type/erc20_paymaster_generator.go @@ -26,10 +26,11 @@ func (e *Erc20PaymasterExecutor) ValidateGas(userOp *model.UserOperation, gasRes } func (e *Erc20PaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { - validationGas := userOp.VerificationGasLimit.String()[0:16] - postOPGas := userOp.CallGasLimit.String()[0:16] - message := validationGas + postOPGas + string(strategy.PayType) - + //[0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature + validationGas := userOp.VerificationGasLimit.String() + postOPGas := userOp.CallGasLimit.String() + message := strategy.PayMasterAddress + validationGas + postOPGas + string(strategy.PayType) + //0000 timestamp /s (convert to hex) 64 signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) if err != nil { return "", err diff --git a/paymaster_pay_type/vertifying_paymaster_generator.go b/paymaster_pay_type/vertifying_paymaster_generator.go index d0692047..43b54dbf 100644 --- a/paymaster_pay_type/vertifying_paymaster_generator.go +++ b/paymaster_pay_type/vertifying_paymaster_generator.go @@ -30,11 +30,11 @@ func (v VerifyingPaymasterExecutor) ValidateGas(userOp *model.UserOperation, res } func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { - //verifying:[0-1]pay type,[1-21]paymaster address,[21-85]valid timestamp,[85-] signature + //[0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature validationGas := userOp.VerificationGasLimit.String() postOPGas := userOp.CallGasLimit.String() - message := validationGas + postOPGas + string(strategy.PayType) - + message := strategy.PayMasterAddress + validationGas + postOPGas + string(strategy.PayType) + //0000 timestamp /s (convert to hex) 64 signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) if err != nil { return "", err diff --git a/service/operator/get_support_entry_point_execute.go b/service/operator/get_support_entry_point_execute.go index ac38f42c..d15f1e35 100644 --- a/service/operator/get_support_entry_point_execute.go +++ b/service/operator/get_support_entry_point_execute.go @@ -8,7 +8,7 @@ import ( func GetSupportEntrypointExecute(network string) (*[]model.EntrypointDomain, error) { entrypoints := make([]model.EntrypointDomain, 0) entrypoints = append(entrypoints, model.EntrypointDomain{ - Address: "0x0576a174D229E3cFA37253523E645A78A0C91B57", + Address: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", Desc: "desc", NetWork: types.Sepolia, StrategyId: "1", diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 36817cab..65cc0181 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -70,7 +70,9 @@ func checkSender(userOp *model.UserOperation, netWork types.Network) error { return nil } func checkInitCode(initCode []byte, network types.Network) error { - + if len(initCode) < 20 { + return xerrors.Errorf("initCode length is less than 20 do not have factory address") + } factoryAddress := common.BytesToAddress(initCode[:20]) if ok, err := chain_service.CheckContractAddressAccess(factoryAddress, network); err != nil { return err From f13a8ca12484034e442e5a30444c7a274c0f7acc Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 15 Mar 2024 17:33:11 +0800 Subject: [PATCH 20/47] fix bug --- service/validator_service/basic_validator.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 65cc0181..f6821eff 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -53,20 +53,14 @@ func ValidateUserOp(userOp *model.UserOperation) error { } func checkSender(userOp *model.UserOperation, netWork types.Network) error { //check sender - - if ok, err := chain_service.CheckContractAddressAccess(userOp.Sender, netWork); err != nil { - return err - } else if !ok { - return xerrors.Errorf("sender address not exist in [%s] network", netWork) + checkOk, checkSenderErr := chain_service.CheckContractAddressAccess(userOp.Sender, netWork) + if !checkOk { + if err := checkInitCode(userOp.InitCode, netWork); err != nil { + return xerrors.Errorf("%s and %s", checkSenderErr.Error(), err.Error()) + } } //check balance - //if userOp.InitCode == "" { - // return xerrors.Errorf("initCode can not be empty if sender is empty") - //} - if err := checkInitCode(userOp.InitCode, netWork); err != nil { - - } return nil } func checkInitCode(initCode []byte, network types.Network) error { @@ -77,9 +71,8 @@ func checkInitCode(initCode []byte, network types.Network) error { if ok, err := chain_service.CheckContractAddressAccess(factoryAddress, network); err != nil { return err } else if !ok { - return xerrors.Errorf("sender address not exist in [%s] network", network) + return xerrors.Errorf("factoryAddress address [factoryAddress] not exist in [%s] network", network) } - // TODO checkFactoryAddress stack //parse its first 20 bytes as a factory address. Record whether the factory is staked, //factory and factoryData - either both exist, or none From 4d1594dac712e262d534ea548e25fdcfbcb662fd Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 15 Mar 2024 20:22:03 +0800 Subject: [PATCH 21/47] fix bug --- common/utils/util.go | 22 +++++++++---------- .../dashboard_service/dashboard_service.go | 4 ++-- service/gas_service/gas_computor.go | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 1290e435..06957105 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -14,17 +14,17 @@ var HexPattern = regexp.MustCompile(`^0x[a-fA-F\d]*$`) func GenerateMockUserOperation() *map[string]any { //TODO use config var MockUserOpData = map[string]any{ - "sender": "0x4A2FD3215420376DA4eD32853C19E4755deeC4D1", - "nonce": "1", - "init_code": "0xe19e9755942bb0bd0cccce25b1742596b8a8250b3bf2c3e700000000000000000000000078d4f01f56b982a3b03c4e127a5d3afa8ebee6860000000000000000000000008b388a082f370d8ac2e2b3997e9151168bd09ff50000000000000000000000000000000000000000000000000000000000000000", - "call_data": "0xb61d27f6000000000000000000000000c206b552ab127608c3f666156c8e03a8471c72df000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", - "call_gas_limit": "39837", - "verification_gas_limit": "100000", - "max_fee_per_gas": "44020", - "max_priority_fee_per_gas": "1743509478", - "pre_verification_gas": "44020", - "signature": "0x760868cd7d9539c6e31c2169c4cab6817beb8247516a90e4301e929011451658623455035b83d38e987ef2e57558695040a25219c39eaa0e31a0ead16a5c925c1c", - "paymaster_and_data": "0x", + "call_data": "0xb61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", + "call_gas_limit": "0x54fa", + "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000", + "max_fee_per_gas": "0x2aa887baca", + "max_priority_fee_per_gas": "0x59682f00", + "nonce": "0x00", + "pre_verification_gas": "0xae64", + "sender": "0xF8498599744BC37e141cb800B67Dbf103a6b5881", + "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", + "verification_gas_limit": "0x05fa35", + "paymaster_and_data": "0x0000000000325602a77416A16136FDafd04b299f", } return &MockUserOpData diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index a820b080..c8bcc704 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -14,7 +14,7 @@ var entryPointSupport = map[string]bool{} func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", - EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", + EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", PayMasterAddress: "0x409646509be42aea79eab370efc2c0ec2e51753b", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, @@ -23,7 +23,7 @@ func init() { } MockStrategyMap["2"] = &model.Strategy{ Id: "2", - EntryPointAddress: "0x0576a174D229E3cFA37253523E645A78A0C91B57", + EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", PayType: types.PayTypeERC20, EntryPointTag: types.EntrypointV06, diff --git a/service/gas_service/gas_computor.go b/service/gas_service/gas_computor.go index d645f520..b2761981 100644 --- a/service/gas_service/gas_computor.go +++ b/service/gas_service/gas_computor.go @@ -25,7 +25,7 @@ func ComputeGas(userOp *model.UserOperation, strategy *model.Strategy) (*model.C Data: userOp.CallData, }) userOpCallGasLimit := userOp.CallGasLimit.Uint64() - if estimateCallGasLimit > userOpCallGasLimit { + if estimateCallGasLimit > userOpCallGasLimit*12/10 { return nil, xerrors.Errorf("estimateCallGasLimit %d > userOpCallGasLimit %d", estimateCallGasLimit, userOpCallGasLimit) } From b15c57b1667911806091ffeb620c72843e57c537 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 18 Mar 2024 12:00:05 +0800 Subject: [PATCH 22/47] generatePaymasterData --- common/types/pay_type.go | 4 +- common/utils/price_util_test.go | 5 ++ .../erc20_paymaster_generator.go | 17 ------ paymaster_pay_type/paymaster_generator.go | 2 +- .../vertifying_paymaster_generator.go | 31 ++++++----- service/operator/try_pay_user_op_execute.go | 52 +++++++++++++++---- .../operator/try_pay_user_op_execute_test.go | 10 ++++ 7 files changed, 76 insertions(+), 45 deletions(-) diff --git a/common/types/pay_type.go b/common/types/pay_type.go index 258a39d9..64cd5968 100644 --- a/common/types/pay_type.go +++ b/common/types/pay_type.go @@ -3,6 +3,6 @@ package types type PayType string const ( - PayTypeVerifying PayType = "0" - PayTypeERC20 PayType = "1" + PayTypeVerifying PayType = "00" + PayTypeERC20 PayType = "01" ) diff --git a/common/utils/price_util_test.go b/common/utils/price_util_test.go index f2e11b61..5c5bbb4e 100644 --- a/common/utils/price_util_test.go +++ b/common/utils/price_util_test.go @@ -3,6 +3,7 @@ package utils import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "fmt" + "strconv" "testing" ) @@ -15,3 +16,7 @@ func TestGetToken(t *testing.T) { price, _ := GetToken(types.ETH, types.OP) fmt.Println(price) } +func TestDemo(t *testing.T) { + str := "0000000000000000000000000000000000000000000000000000000000000002" + fmt.Printf(strconv.Itoa(len(str))) +} diff --git a/paymaster_pay_type/erc20_paymaster_generator.go b/paymaster_pay_type/erc20_paymaster_generator.go index 85d3bf70..5b003b7a 100644 --- a/paymaster_pay_type/erc20_paymaster_generator.go +++ b/paymaster_pay_type/erc20_paymaster_generator.go @@ -2,9 +2,7 @@ package paymaster_pay_type import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" - "encoding/hex" "golang.org/x/xerrors" "math/big" ) @@ -24,18 +22,3 @@ func (e *Erc20PaymasterExecutor) ValidateGas(userOp *model.UserOperation, gasRes } return nil } - -func (e *Erc20PaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { - //[0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature - validationGas := userOp.VerificationGasLimit.String() - postOPGas := userOp.CallGasLimit.String() - message := strategy.PayMasterAddress + validationGas + postOPGas + string(strategy.PayType) - //0000 timestamp /s (convert to hex) 64 - signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) - if err != nil { - return "", err - } - signatureStr := hex.EncodeToString(signatureByte) - message = message + signatureStr - return message, nil -} diff --git a/paymaster_pay_type/paymaster_generator.go b/paymaster_pay_type/paymaster_generator.go index 89eff3ec..59a44999 100644 --- a/paymaster_pay_type/paymaster_generator.go +++ b/paymaster_pay_type/paymaster_generator.go @@ -16,7 +16,7 @@ func init() { } type PaymasterPayTypeExecutor interface { - GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) + //GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) ValidateGas(userOp *model.UserOperation, response *model.ComputeGasResponse, strategy *model.Strategy) error } diff --git a/paymaster_pay_type/vertifying_paymaster_generator.go b/paymaster_pay_type/vertifying_paymaster_generator.go index 43b54dbf..d1e81d60 100644 --- a/paymaster_pay_type/vertifying_paymaster_generator.go +++ b/paymaster_pay_type/vertifying_paymaster_generator.go @@ -2,9 +2,7 @@ package paymaster_pay_type import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" - "encoding/hex" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" "math/big" @@ -29,17 +27,18 @@ func (v VerifyingPaymasterExecutor) ValidateGas(userOp *model.UserOperation, res return nil } -func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { - //[0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature - validationGas := userOp.VerificationGasLimit.String() - postOPGas := userOp.CallGasLimit.String() - message := strategy.PayMasterAddress + validationGas + postOPGas + string(strategy.PayType) - //0000 timestamp /s (convert to hex) 64 - signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) - if err != nil { - return "", err - } - signatureStr := hex.EncodeToString(signatureByte) - message = message + signatureStr - return message, nil -} +// +//func (v VerifyingPaymasterExecutor) GeneratePayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse, extra map[string]any) (string, error) { +// //[0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature +// validationGas := userOp.VerificationGasLimit.String() +// postOPGas := userOp.CallGasLimit.String() +// message := strategy.PayMasterAddress + validationGas + postOPGas + string(strategy.PayType) +// //0000 timestamp /s (convert to hex) 64 +// signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) +// if err != nil { +// return "", err +// } +// signatureStr := hex.EncodeToString(signatureByte) +// message = message + signatureStr +// return message, nil +//} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 168ddcc0..864cabbf 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -5,15 +5,17 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/types" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/conf" - "AAStarCommunity/EthPaymaster_BackService/paymaster_pay_type" "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "AAStarCommunity/EthPaymaster_BackService/service/gas_service" "AAStarCommunity/EthPaymaster_BackService/service/pay_service" "AAStarCommunity/EthPaymaster_BackService/service/validator_service" "encoding/hex" + "fmt" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" + "strconv" + "time" ) func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserOpResponse, error) { @@ -65,12 +67,13 @@ func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserO } var paymasterAndData string - if paymasterAndDataRes, err := getPayMasterAndData(strategy, userOp, gasResponse); err != nil { + var paymasterSignature string + if paymasterAndDataRes, paymasterSignatureRes, err := getPayMasterAndData(strategy, userOp, gasResponse); err != nil { return nil, err } else { paymasterAndData = paymasterAndDataRes + paymasterSignature = paymasterSignatureRes } - paymasterSignature := getPayMasterSignature(strategy, userOp) //validatePaymasterUserOp var result = &model.TryPayUserOpResponse{ @@ -125,13 +128,44 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } -func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, error) { - paymasterDataExecutor := paymaster_pay_type.GetPaymasterDataExecutor(strategy.PayType) - if paymasterDataExecutor == nil { - return "", xerrors.Errorf("Not Support PayType: [%w]", strategy.PayType) +func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, string, error) { + return generatePayMasterAndData(strategy) +} + +func generatePayMasterAndData(strategy *model.Strategy) (string, string, error) { + //v0.7 [0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature + //v0.6 [0:20)paymaster address,[20:22)payType, [22:86)start Time ,[86:150)typeId, [53:117)valid timestamp, [117:) signature + //validationGas := userOp.VerificationGasLimit.String() + //postOPGas := userOp.CallGasLimit.String() + + message := fmt.Sprintf("%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), getValidTime()) + signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) + if err != nil { + return "", "", err + } + + signatureStr := hex.EncodeToString(signatureByte) + message = message + signatureStr + return message, signatureStr, nil +} +func getValidTime() string { + currentTime := time.Now() + currentTimestamp := currentTime.Unix() + futureTime := currentTime.Add(15 * time.Minute) + futureTimestamp := futureTime.Unix() + currentTimestampStr := strconv.FormatInt(currentTimestamp, 10) + futureTimestampStr := strconv.FormatInt(futureTimestamp, 10) + currentTimestampStrSupply := SupplyZero(currentTimestampStr, 64) + futureTimestampStrSupply := SupplyZero(futureTimestampStr, 64) + return currentTimestampStrSupply + futureTimestampStrSupply +} +func SupplyZero(prefix string, maxTo int) string { + padding := maxTo - len(prefix) + if padding > 0 { + prefix = "0" + prefix + prefix = fmt.Sprintf("%0*s", maxTo, prefix) } - extra := make(map[string]any) - return paymasterDataExecutor.GeneratePayMasterAndData(strategy, userOp, gasResponse, extra) + return prefix } func strategyGenerate(request *model.TryPayUserOpRequest) (*model.Strategy, error) { diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 49905aff..79d44691 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -3,6 +3,7 @@ package operator import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "encoding/json" "fmt" "github.com/stretchr/testify/assert" @@ -23,3 +24,12 @@ func getMockTryPayUserOpRequest() *model.TryPayUserOpRequest { UserOp: *utils.GenerateMockUserOperation(), } } + +func TestGenerateTestData(t *testing.T) { + strategy := dashboard_service.GetStrategyById("1") + str, signature, err := generatePayMasterAndData(strategy) + assert.NoError(t, err) + fmt.Println(str) + fmt.Println(signature) + fmt.Println(len(signature)) +} From 8efed7c223e779d73a317213866d24dfb0b9a585 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 18 Mar 2024 18:35:16 +0800 Subject: [PATCH 23/47] add GetCoinPrice --- common/utils/price_util.go | 32 +++++++++++++++++++++++++++++++- common/utils/price_util_test.go | 4 ++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/common/utils/price_util.go b/common/utils/price_util.go index 403c7436..d85d5af7 100644 --- a/common/utils/price_util.go +++ b/common/utils/price_util.go @@ -2,15 +2,21 @@ package utils import ( "AAStarCommunity/EthPaymaster_BackService/common/types" + "fmt" "golang.org/x/xerrors" "io" + "io/ioutil" + "log" "net/http" + "net/url" + "os" "strconv" "strings" ) var ( - URLMap = map[types.TokenType]string{} + URLMap = map[types.TokenType]string{} + httpClient = &http.Client{} ) type Price struct { @@ -56,3 +62,27 @@ func GetToken(fromToken types.TokenType, toToken types.TokenType) (float64, erro return formTokenPrice / toTokenPrice, nil } + +func GetCoinMarketPrice() { + req, err := http.NewRequest("GET", "https://pro-api.coinmarketcap.com/v2/tools/price-conversion", nil) + if err != nil { + log.Print(err) + os.Exit(1) + } + q := url.Values{} + q.Add("amount", "2") + q.Add("symbol", "BTC") + q.Add("convert", "USD") + + req.Header.Set("Accepts", "application/json") + req.Header.Add("X-CMC_PRO_API_KEY", "a1441679-b8fd-49a0-aa47-51f88f7d3d52") + req.URL.RawQuery = q.Encode() + resp, err := httpClient.Do(req) + if err != nil { + fmt.Println("Error sending request to server") + os.Exit(1) + } + fmt.Println(resp.Status) + respBody, _ := ioutil.ReadAll(resp.Body) + fmt.Println(string(respBody)) +} diff --git a/common/utils/price_util_test.go b/common/utils/price_util_test.go index 5c5bbb4e..339f06a3 100644 --- a/common/utils/price_util_test.go +++ b/common/utils/price_util_test.go @@ -20,3 +20,7 @@ func TestDemo(t *testing.T) { str := "0000000000000000000000000000000000000000000000000000000000000002" fmt.Printf(strconv.Itoa(len(str))) } + +func TestGetCoinMarketPrice(t *testing.T) { + GetCoinMarketPrice() +} From 37316b1e65dc27e21644c551e8676202af46ad72 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 18 Mar 2024 22:15:24 +0800 Subject: [PATCH 24/47] update PackUserOp --- service/operator/try_pay_user_op_execute.go | 46 +++++++++++++++ .../operator/try_pay_user_op_execute_test.go | 58 +++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 864cabbf..a74a8539 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -11,10 +11,13 @@ import ( "AAStarCommunity/EthPaymaster_BackService/service/pay_service" "AAStarCommunity/EthPaymaster_BackService/service/validator_service" "encoding/hex" + "encoding/json" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" "strconv" + "strings" "time" ) @@ -128,6 +131,49 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } +func packUserOp(userOp *model.UserOperation) (string, error) { + abiEncoder, err := abi.JSON(strings.NewReader(`[ + {"type":"address","name":"sender"}, + {"type":"uint256","name":"nonce"}, + {"type":"bytes","name":"init_code"}, + {"type":"bytes","name":"call_data"}, + {"type":"uint256","name":"call_gas_limit"}, + {"type":"uint256","name":"verification_gas_limit"}, + {"type":"uint256","name":"pre_verification_gas"}, + {"type":"uint256","name":"max_fee_per_gas"}, + {"type":"uint256","name":"max_priority_fee_per_gas"}, + {"type":"bytes","name":"signature"}, + {"type":"bytes","name":"paymaster_and_data"} + ]`)) + if err != nil { + return "", err + } + + encoded, err := abiEncoder.Pack("", userOp.Sender.String(), userOp.Nonce, userOp.InitCode, + userOp.CallData, userOp.CallGasLimit, userOp.VerificationGasLimit, userOp.PreVerificationGas, + userOp.MaxFeePerGas, userOp.MaxPriorityFeePerGas) + if err != nil { + return "", err + } + hexString := hex.EncodeToString(encoded) + return hexString, nil +} + +func packUserOpSimple(userOp *model.UserOperation) (string, error) { + data, err := json.Marshal(userOp) + if err != nil { + return "", err + } + hexString := hex.EncodeToString(data) + + return hexString, nil + +} + +// func UserOpHash(userOp *model.UserOperation, chainId string, strategy *model.Strategy, validStart string, validEnd string) []byte { +// packUserOp(userOp) +// +// } func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, string, error) { return generatePayMasterAndData(strategy) } diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 79d44691..3ff1749b 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -33,3 +33,61 @@ func TestGenerateTestData(t *testing.T) { fmt.Println(signature) fmt.Println(len(signature)) } +func TestPackUserOp(t *testing.T) { + + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + userOp.Signature = nil + userOp.PaymasterAndData = nil + res, err := packUserOp(userOp) + + assert.NoError(t, err) + + fmt.Println(res) +} +func TestPackUserOpV2(t *testing.T) { + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + userOp.Signature = nil + userOp.PaymasterAndData = nil + res, err := packUserOpSimple(userOp) + assert.NoError(t, err) + fmt.Println(res) +} +func TestUserOP(t *testing.T) { + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + fmt.Println(userOp.Sender.String()) +} +func TestGenerateTestPaymaterDataparse(t *testing.T) { + //contractABI, err := abi.JSON([]byte(`[ + // { + // "constant": false, + // "inputs": [ + // { + // "name": "userOp", + // "type": "tuple" + // }, + // { + // "name": "requiredPreFund", + // "type": "uint256" + // } + // ], + // "name": "_validatePaymasterUserOp", + // "outputs": [ + // { + // "name": "context", + // "type": "bytes" + // }, + // { + // "name": "validationData", + // "type": "uint256" + // } + // ], + // "payable": false, + // "stateMutability": "nonpayable", + // "type": "function" + // } + //]`)) + //if err != nil { + // log.Fatal(err) + //} + //str := "0x +} From fd480828e065f084a1625032029b5710093c9860 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 18 Mar 2024 22:42:40 +0800 Subject: [PATCH 25/47] update PackUserOp --- common/model/user_operation.go | 3 + service/operator/try_pay_user_op_execute.go | 83 ++++++++++++++++--- .../operator/try_pay_user_op_execute_test.go | 4 +- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 9c63bc2f..33027aea 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -33,6 +33,9 @@ type UserOperation struct { Signature []byte `json:"signature" mapstructure:"signature" binding:"required"` PaymasterAndData []byte `json:"paymaster_and_data" mapstructure:"paymaster_and_data"` } +type UserOperationSimple struct { + Sender []byte `json:"sender" mapstructure:"sender" binding:"required,hexParam"` +} // PackUserOperation entrypoint v0.0.67 type PackUserOperation struct { diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index a74a8539..3f3d5d58 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -133,23 +133,82 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation } func packUserOp(userOp *model.UserOperation) (string, error) { abiEncoder, err := abi.JSON(strings.NewReader(`[ - {"type":"address","name":"sender"}, - {"type":"uint256","name":"nonce"}, - {"type":"bytes","name":"init_code"}, - {"type":"bytes","name":"call_data"}, - {"type":"uint256","name":"call_gas_limit"}, - {"type":"uint256","name":"verification_gas_limit"}, - {"type":"uint256","name":"pre_verification_gas"}, - {"type":"uint256","name":"max_fee_per_gas"}, - {"type":"uint256","name":"max_priority_fee_per_gas"}, - {"type":"bytes","name":"signature"}, - {"type":"bytes","name":"paymaster_and_data"} +{ + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "op", + "type": "tuple" + } + ], + "name": "test", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ]`)) if err != nil { return "", err } - encoded, err := abiEncoder.Pack("", userOp.Sender.String(), userOp.Nonce, userOp.InitCode, + encoded, err := abiEncoder.Pack("test", userOp.Sender.String(), userOp.Nonce, userOp.InitCode, userOp.CallData, userOp.CallGasLimit, userOp.VerificationGasLimit, userOp.PreVerificationGas, userOp.MaxFeePerGas, userOp.MaxPriorityFeePerGas) if err != nil { diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 3ff1749b..72a7a707 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -34,14 +34,12 @@ func TestGenerateTestData(t *testing.T) { fmt.Println(len(signature)) } func TestPackUserOp(t *testing.T) { - userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) userOp.Signature = nil userOp.PaymasterAndData = nil - res, err := packUserOp(userOp) + res, err := packUserOp(userOp) assert.NoError(t, err) - fmt.Println(res) } func TestPackUserOpV2(t *testing.T) { From 2480c96644a8d763cce6646f7f5e5d0d9c8f93aa Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 18 Mar 2024 23:02:51 +0800 Subject: [PATCH 26/47] update PackUserOp --- service/operator/try_pay_user_op_execute.go | 10 ++++------ service/operator/try_pay_user_op_execute_test.go | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 3f3d5d58..1c343d1b 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -133,7 +133,7 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation } func packUserOp(userOp *model.UserOperation) (string, error) { abiEncoder, err := abi.JSON(strings.NewReader(`[ -{ + { "inputs": [ { "components": [ @@ -194,7 +194,7 @@ func packUserOp(userOp *model.UserOperation) (string, error) { } ], "internalType": "struct UserOperation", - "name": "op", + "name": "userOp", "type": "tuple" } ], @@ -203,14 +203,12 @@ func packUserOp(userOp *model.UserOperation) (string, error) { "stateMutability": "nonpayable", "type": "function" } - ]`)) +]`)) if err != nil { return "", err } - encoded, err := abiEncoder.Pack("test", userOp.Sender.String(), userOp.Nonce, userOp.InitCode, - userOp.CallData, userOp.CallGasLimit, userOp.VerificationGasLimit, userOp.PreVerificationGas, - userOp.MaxFeePerGas, userOp.MaxPriorityFeePerGas) + encoded, err := abiEncoder.Pack("test", userOp) if err != nil { return "", err } diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 72a7a707..b9da05e5 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -35,12 +35,13 @@ func TestGenerateTestData(t *testing.T) { } func TestPackUserOp(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOp.Signature = nil userOp.PaymasterAndData = nil - + userOp.Signature = nil res, err := packUserOp(userOp) + assert.NoError(t, err) fmt.Println(res) + } func TestPackUserOpV2(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) From ac2e4d5d94b12840f6787f4af80db0e73142cae3 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 11:00:34 +0800 Subject: [PATCH 27/47] update PackUserOp --- service/chain_service/chain_service.go | 7 ++++ service/chain_service/chain_test.go | 6 +++ service/operator/try_pay_user_op_execute.go | 38 ++++++++++--------- .../operator/try_pay_user_op_execute_test.go | 15 +++----- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/service/chain_service/chain_service.go b/service/chain_service/chain_service.go index 27e0c244..507082fe 100644 --- a/service/chain_service/chain_service.go +++ b/service/chain_service/chain_service.go @@ -160,3 +160,10 @@ func GetAddressTokenBalance(network types.Network, address common.Address, token return balanceResultFloat, nil } +func GetChainId(chain types.Network) (*big.Int, error) { + client, exist := EthCompatibleNetWorkClientMap[chain] + if !exist { + return nil, xerrors.Errorf("chain Client [%s] not exist", chain) + } + return client.ChainID(context.Background()) +} diff --git a/service/chain_service/chain_test.go b/service/chain_service/chain_test.go index 729d1154..7c55121e 100644 --- a/service/chain_service/chain_test.go +++ b/service/chain_service/chain_test.go @@ -36,3 +36,9 @@ func TestGetAddressTokenBalance(t *testing.T) { assert.NoError(t, err) fmt.Println(res) } + +func TestGetChainId(t *testing.T) { + res, err := GetChainId(types.Sepolia) + assert.NoError(t, err) + fmt.Println(res) +} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 1c343d1b..1b8fa678 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -11,10 +11,11 @@ import ( "AAStarCommunity/EthPaymaster_BackService/service/pay_service" "AAStarCommunity/EthPaymaster_BackService/service/validator_service" "encoding/hex" - "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" "golang.org/x/xerrors" "strconv" "strings" @@ -131,7 +132,7 @@ func getPayMasterSignature(strategy *model.Strategy, userOp *model.UserOperation signatureBytes, _ := utils.SignUserOp("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", userOp) return hex.EncodeToString(signatureBytes) } -func packUserOp(userOp *model.UserOperation) (string, error) { +func packUserOp(userOp *model.UserOperation) (string, []byte, error) { abiEncoder, err := abi.JSON(strings.NewReader(`[ { "inputs": [ @@ -205,32 +206,35 @@ func packUserOp(userOp *model.UserOperation) (string, error) { } ]`)) if err != nil { - return "", err + return "", nil, err } encoded, err := abiEncoder.Pack("test", userOp) if err != nil { - return "", err + return "", nil, err } hexString := hex.EncodeToString(encoded) - return hexString, nil + return hexString, encoded, nil } -func packUserOpSimple(userOp *model.UserOperation) (string, error) { - data, err := json.Marshal(userOp) +func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { + _, packUserOpStrByte, err := packUserOp(userOp) if err != nil { - return "", err - } - hexString := hex.EncodeToString(data) - - return hexString, nil + return nil, nil + } + chainId, err := chain_service.GetChainId(strategy.NetWork) + if err != nil { + return nil, nil + } + input := []interface{}{packUserOpStrByte, chainId.Int64(), strategy.PayMasterAddress, userOp.Nonce, validStart, validEnd} + encodeRes, err := rlp.EncodeToBytes(input) + if err != nil { + return nil, nil + } + byteRes := crypto.Keccak256(encodeRes) + return byteRes, nil } - -// func UserOpHash(userOp *model.UserOperation, chainId string, strategy *model.Strategy, validStart string, validEnd string) []byte { -// packUserOp(userOp) -// -// } func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, string, error) { return generatePayMasterAndData(strategy) } diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index b9da05e5..cfdb7af2 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -37,20 +37,17 @@ func TestPackUserOp(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) userOp.PaymasterAndData = nil userOp.Signature = nil - res, err := packUserOp(userOp) + res, byteres, err := packUserOp(userOp) assert.NoError(t, err) fmt.Println(res) - + fmt.Println(byteres) } -func TestPackUserOpV2(t *testing.T) { - userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOp.Signature = nil - userOp.PaymasterAndData = nil - res, err := packUserOpSimple(userOp) - assert.NoError(t, err) - fmt.Println(res) + +func TestUserOpHash(t *testing.T) { + } + func TestUserOP(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) fmt.Println(userOp.Sender.String()) From d68773dd67fa12dfa09ea8ec1cbdaf743f593e81 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 12:17:54 +0800 Subject: [PATCH 28/47] update PackUserOp --- service/operator/try_pay_user_op_execute.go | 41 ++++++++++++------- .../operator/try_pay_user_op_execute_test.go | 10 ++++- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 1b8fa678..957a22f5 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" "golang.org/x/xerrors" "strconv" "strings" @@ -199,7 +198,7 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { "type": "tuple" } ], - "name": "test", + "name": "UserOp", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -209,7 +208,7 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { return "", nil, err } - encoded, err := abiEncoder.Pack("test", userOp) + encoded, err := abiEncoder.Pack("UserOp", userOp) if err != nil { return "", nil, err } @@ -221,41 +220,53 @@ func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStar _, packUserOpStrByte, err := packUserOp(userOp) if err != nil { return nil, nil - } chainId, err := chain_service.GetChainId(strategy.NetWork) if err != nil { return nil, nil } - input := []interface{}{packUserOpStrByte, chainId.Int64(), strategy.PayMasterAddress, userOp.Nonce, validStart, validEnd} - encodeRes, err := rlp.EncodeToBytes(input) + encodeHash := crypto.Keccak256Hash(packUserOpStrByte, chainId.Bytes(), []byte(strategy.PayMasterAddress), userOp.Nonce.Bytes(), []byte(validStart), []byte(validEnd)) if err != nil { return nil, nil } - byteRes := crypto.Keccak256(encodeRes) + byteRes := crypto.Keccak256(encodeHash.Bytes()) return byteRes, nil } + func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, string, error) { - return generatePayMasterAndData(strategy) + return generatePayMasterAndData(userOp, strategy) } -func generatePayMasterAndData(strategy *model.Strategy) (string, string, error) { +func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strategy) (string, string, error) { //v0.7 [0:20)paymaster address,[20:36)validation gas, [36:52)postop gas,[52:53)typeId, [53:117)valid timestamp, [117:) signature //v0.6 [0:20)paymaster address,[20:22)payType, [22:86)start Time ,[86:150)typeId, [53:117)valid timestamp, [117:) signature //validationGas := userOp.VerificationGasLimit.String() //postOPGas := userOp.CallGasLimit.String() - - message := fmt.Sprintf("%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), getValidTime()) - signatureByte, err := utils.SignMessage("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", message) + validStart, validEnd := getValidTime() + message := fmt.Sprintf("%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart+validEnd) + signatureByte, err := SignPaymaster(userOp, strategy, validStart, validEnd) if err != nil { return "", "", err } - signatureStr := hex.EncodeToString(signatureByte) message = message + signatureStr return message, signatureStr, nil } -func getValidTime() string { + +func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { + userOpHash, err := UserOpHash(userOp, strategy, validStart, validEnd) + if err != nil { + return nil, err + } + privateKey, err := crypto.HexToECDSA("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421") + if err != nil { + return nil, err + } + signature, err := crypto.Sign(userOpHash, privateKey) + return signature, err +} + +func getValidTime() (string, string) { currentTime := time.Now() currentTimestamp := currentTime.Unix() futureTime := currentTime.Add(15 * time.Minute) @@ -264,7 +275,7 @@ func getValidTime() string { futureTimestampStr := strconv.FormatInt(futureTimestamp, 10) currentTimestampStrSupply := SupplyZero(currentTimestampStr, 64) futureTimestampStrSupply := SupplyZero(futureTimestampStr, 64) - return currentTimestampStrSupply + futureTimestampStrSupply + return currentTimestampStrSupply, futureTimestampStrSupply } func SupplyZero(prefix string, maxTo int) string { padding := maxTo - len(prefix) diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index cfdb7af2..37b48e1c 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -4,6 +4,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "encoding/hex" "encoding/json" "fmt" "github.com/stretchr/testify/assert" @@ -27,7 +28,8 @@ func getMockTryPayUserOpRequest() *model.TryPayUserOpRequest { func TestGenerateTestData(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") - str, signature, err := generatePayMasterAndData(strategy) + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + str, signature, err := generatePayMasterAndData(userOp, strategy) assert.NoError(t, err) fmt.Println(str) fmt.Println(signature) @@ -45,6 +47,12 @@ func TestPackUserOp(t *testing.T) { } func TestUserOpHash(t *testing.T) { + validStart, validEnd := getValidTime() + strategy := dashboard_service.GetStrategyById("1") + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + userOpHash, err := UserOpHash(userOp, strategy, validStart, validEnd) + assert.NoError(t, err) + fmt.Println(hex.EncodeToString(userOpHash)) } From 1282794b03d485101868a6c43f8ee7e889e6e3a4 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 14:12:18 +0800 Subject: [PATCH 29/47] update PackUserOp --- service/operator/try_pay_user_op_execute.go | 55 ++++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 957a22f5..95ad8909 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -219,18 +219,61 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { _, packUserOpStrByte, err := packUserOp(userOp) if err != nil { - return nil, nil + return nil, err + } + abiEncoder, err := abi.JSON(strings.NewReader(`[ + { + "name": "bar", + "type": "function", + "inputs": [ + { + "type": "uint256", + "name": "userOp" + }, + { + "type": "uint256", + "name": "_chainID" + }, + { + "type": "address", + "name": "_thisAddress" + }, + { + "type": "uint256", + "name": "_senderNonce" + }, + { + "type": "uint256", + "name": "_validUntil" + }, + { + "type": "uint256", + "name": "_validAfter" + } + ], + "outputs": [ + { + "type": "bytes32", + "name": "_result" + } + ] + } +]`)) + if err != nil { + return nil, err } chainId, err := chain_service.GetChainId(strategy.NetWork) if err != nil { - return nil, nil + return nil, err } - encodeHash := crypto.Keccak256Hash(packUserOpStrByte, chainId.Bytes(), []byte(strategy.PayMasterAddress), userOp.Nonce.Bytes(), []byte(validStart), []byte(validEnd)) + data, err := abiEncoder.Pack("bar", &packUserOpStrByte, &chainId, &strategy.PayMasterAddress, &userOp.Nonce, &validStart, &validEnd) if err != nil { - return nil, nil + return nil, err } - byteRes := crypto.Keccak256(encodeHash.Bytes()) - return byteRes, nil + encodeHash := crypto.Keccak256Hash(data) + + return encodeHash.Bytes(), nil + } func getPayMasterAndData(strategy *model.Strategy, userOp *model.UserOperation, gasResponse *model.ComputeGasResponse) (string, string, error) { From ca6fcc54617cfe8eaf4bb3bd65cd2c388efe15d7 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 15:03:39 +0800 Subject: [PATCH 30/47] update PackUserOp --- service/operator/try_pay_user_op_execute.go | 98 ++++++++++++------- .../operator/try_pay_user_op_execute_test.go | 5 +- 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 95ad8909..c15a6f14 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "golang.org/x/xerrors" + "math/big" "strconv" "strings" "time" @@ -216,62 +217,82 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { return hexString, encoded, nil } -func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { +func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart *big.Int, validEnd *big.Int) ([]byte, error) { _, packUserOpStrByte, err := packUserOp(userOp) if err != nil { return nil, err } + abiEncoder, err := abi.JSON(strings.NewReader(`[ { - "name": "bar", - "type": "function", "inputs": [ - { - "type": "uint256", - "name": "userOp" - }, - { - "type": "uint256", - "name": "_chainID" - }, - { - "type": "address", - "name": "_thisAddress" - }, - { - "type": "uint256", - "name": "_senderNonce" - }, { - "type": "uint256", - "name": "_validUntil" - }, - { - "type": "uint256", - "name": "_validAfter" + "components": [ + { + "internalType": "bytes", + "name": "userOpHash", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "address", + "type": "address" + }, + { + "internalType": "uint48", + "name": "validUtil", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + } + ], + "internalType": "struct hash", + "name": "hash", + "type": "tuple" } ], - "outputs": [ - { - "type": "bytes32", - "name": "_result" - } - ] + "name": "Hash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ]`)) - if err != nil { - return nil, err - } chainId, err := chain_service.GetChainId(strategy.NetWork) if err != nil { return nil, err } - data, err := abiEncoder.Pack("bar", &packUserOpStrByte, &chainId, &strategy.PayMasterAddress, &userOp.Nonce, &validStart, &validEnd) + hashStruct := struct { + UserOpHash []byte + ChainId *big.Int + Address common.Address + Nonce *big.Int + ValidUtil *big.Int + ValidAfter *big.Int + }{ + packUserOpStrByte, + chainId, + common.HexToAddress(strategy.PayMasterAddress), + userOp.Nonce, + validStart, + validEnd, + } + + chainId.Int64() + + data, err := abiEncoder.Pack("Hash", hashStruct) if err != nil { return nil, err } + fmt.Println(hex.EncodeToString(data)) encodeHash := crypto.Keccak256Hash(data) - return encodeHash.Bytes(), nil } @@ -297,7 +318,10 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat } func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { - userOpHash, err := UserOpHash(userOp, strategy, validStart, validEnd) + //string to int + validStartInt, _ := strconv.ParseInt(validStart, 10, 64) + validEndInt, _ := strconv.ParseInt(validEnd, 10, 64) + userOpHash, err := UserOpHash(userOp, strategy, big.NewInt(validStartInt), big.NewInt(validEndInt)) if err != nil { return nil, err } diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 37b48e1c..9389c068 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "github.com/stretchr/testify/assert" + "math/big" "testing" ) @@ -47,13 +48,11 @@ func TestPackUserOp(t *testing.T) { } func TestUserOpHash(t *testing.T) { - validStart, validEnd := getValidTime() strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOpHash, err := UserOpHash(userOp, strategy, validStart, validEnd) + userOpHash, err := UserOpHash(userOp, strategy, big.NewInt(1), big.NewInt(2)) assert.NoError(t, err) fmt.Println(hex.EncodeToString(userOpHash)) - } func TestUserOP(t *testing.T) { From 7c5835850a0fb9a6fb0beaf07f1b13216fc50147 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 15:36:07 +0800 Subject: [PATCH 31/47] update PackUserOp --- common/utils/util.go | 2 +- service/dashboard_service/dashboard_service.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 06957105..5a043d82 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -19,7 +19,7 @@ func GenerateMockUserOperation() *map[string]any { "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000", "max_fee_per_gas": "0x2aa887baca", "max_priority_fee_per_gas": "0x59682f00", - "nonce": "0x00", + "nonce": "0x01", "pre_verification_gas": "0xae64", "sender": "0xF8498599744BC37e141cb800B67Dbf103a6b5881", "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index c8bcc704..71eef4a7 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -15,7 +15,7 @@ func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0x409646509be42aea79eab370efc2c0ec2e51753b", + PayMasterAddress: "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b44", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, EntryPointTag: types.EntrypointV06, @@ -24,7 +24,7 @@ func init() { MockStrategyMap["2"] = &model.Strategy{ Id: "2", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0x0000000000325602a77416A16136FDafd04b299f", + PayMasterAddress: "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b44", PayType: types.PayTypeERC20, EntryPointTag: types.EntrypointV06, NetWork: types.Sepolia, From 6921a7b8fc1fdd4258294911591d218bc42aba26 Mon Sep 17 00:00:00 2001 From: 0xRory <0x1rory@gmail.com> Date: Tue, 19 Mar 2024 16:07:40 +0800 Subject: [PATCH 32/47] feat: change call methods function --- service/operator/try_pay_user_op_execute.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index c15a6f14..8f3ea861 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -208,8 +208,9 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { if err != nil { return "", nil, err } + method := abiEncoder.Methods["UserOp"] + encoded, err := method.Inputs.Pack(userOp) - encoded, err := abiEncoder.Pack("UserOp", userOp) if err != nil { return "", nil, err } From 977851771b840f9daf8521d435901164a173f191 Mon Sep 17 00:00:00 2001 From: 0xRory <0x1rory@gmail.com> Date: Tue, 19 Mar 2024 17:10:00 +0800 Subject: [PATCH 33/47] feat: split string --- service/operator/try_pay_user_op_execute.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 8f3ea861..7a7e8511 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -204,17 +204,24 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { "stateMutability": "nonpayable", "type": "function" } -]`)) + ]`)) if err != nil { return "", nil, err } method := abiEncoder.Methods["UserOp"] encoded, err := method.Inputs.Pack(userOp) + if err != nil { return "", nil, err } + //https://github.com/jayden-sudo/SoulWalletCore/blob/dc76bdb9a156d4f99ef41109c59ab99106c193ac/contracts/utils/CalldataPack.sol#L51-L65 + + hexString := hex.EncodeToString(encoded) + + hexString = hexString[64:] + hexString = hexString[:640] return hexString, encoded, nil } From bbb2fd9131c217749be77728b41556519d27fe99 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 19 Mar 2024 18:13:38 +0800 Subject: [PATCH 34/47] update PackUserOp --- common/utils/util.go | 2 +- service/operator/try_pay_user_op_execute.go | 114 +++++++----------- .../operator/try_pay_user_op_execute_test.go | 52 +++++++- 3 files changed, 93 insertions(+), 75 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 5a043d82..06957105 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -19,7 +19,7 @@ func GenerateMockUserOperation() *map[string]any { "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000", "max_fee_per_gas": "0x2aa887baca", "max_priority_fee_per_gas": "0x59682f00", - "nonce": "0x01", + "nonce": "0x00", "pre_verification_gas": "0xae64", "sender": "0xF8498599744BC37e141cb800B67Dbf103a6b5881", "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 7a7e8511..b40e6e4a 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -211,97 +211,67 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { method := abiEncoder.Methods["UserOp"] encoded, err := method.Inputs.Pack(userOp) - if err != nil { return "", nil, err } //https://github.com/jayden-sudo/SoulWalletCore/blob/dc76bdb9a156d4f99ef41109c59ab99106c193ac/contracts/utils/CalldataPack.sol#L51-L65 - hexString := hex.EncodeToString(encoded) hexString = hexString[64:] - hexString = hexString[:640] + hexLen := len(hexString) + hexString = hexString[:hexLen-128] return hexString, encoded, nil } -func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart *big.Int, validEnd *big.Int) ([]byte, error) { - _, packUserOpStrByte, err := packUserOp(userOp) +func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart *big.Int, validEnd *big.Int) ([]byte, string, error) { + packUserOpStr, _, err := packUserOp(userOp) if err != nil { - return nil, err + return nil, "", err } - - abiEncoder, err := abi.JSON(strings.NewReader(`[ - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "userOpHash", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "address", - "type": "address" - }, - { - "internalType": "uint48", - "name": "validUtil", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - } - ], - "internalType": "struct hash", - "name": "hash", - "type": "tuple" - } - ], - "name": "Hash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -]`)) - chainId, err := chain_service.GetChainId(strategy.NetWork) + // + bytesTy, err := abi.NewType("bytes", "", nil) if err != nil { - return nil, err + fmt.Println(err) } - hashStruct := struct { - UserOpHash []byte - ChainId *big.Int - Address common.Address - Nonce *big.Int - ValidUtil *big.Int - ValidAfter *big.Int - }{ - packUserOpStrByte, - chainId, - common.HexToAddress(strategy.PayMasterAddress), - userOp.Nonce, - validStart, - validEnd, + uint256Ty, err := abi.NewType("uint256", "", nil) + if err != nil { + fmt.Println(err) } + addressTy, _ := abi.NewType("address", "", nil) + arguments := abi.Arguments{ + { + Type: bytesTy, + }, + { + Type: uint256Ty, + }, + { + Type: addressTy, + }, + { + Type: uint256Ty, + }, + { + Type: uint256Ty, + }, + { + Type: uint256Ty, + }, + } + chainId, err := chain_service.GetChainId(strategy.NetWork) + if err != nil { + return nil, "", err + } + packUserOpStrByteNew, _ := hex.DecodeString(packUserOpStr) chainId.Int64() - - data, err := abiEncoder.Pack("Hash", hashStruct) + bytesRes, err := arguments.Pack(packUserOpStrByteNew, chainId, common.HexToAddress(strategy.PayMasterAddress), userOp.Nonce, validStart, validEnd) if err != nil { - return nil, err + return nil, "", err } - fmt.Println(hex.EncodeToString(data)) - encodeHash := crypto.Keccak256Hash(data) - return encodeHash.Bytes(), nil + encodeHash := crypto.Keccak256Hash(bytesRes) + return encodeHash.Bytes(), hex.EncodeToString(bytesRes), nil } @@ -329,7 +299,7 @@ func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validS //string to int validStartInt, _ := strconv.ParseInt(validStart, 10, 64) validEndInt, _ := strconv.ParseInt(validEnd, 10, 64) - userOpHash, err := UserOpHash(userOp, strategy, big.NewInt(validStartInt), big.NewInt(validEndInt)) + userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(validStartInt), big.NewInt(validEndInt)) if err != nil { return nil, err } diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 9389c068..15e0db92 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -7,6 +7,8 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "math/big" "testing" @@ -41,17 +43,24 @@ func TestPackUserOp(t *testing.T) { userOp.PaymasterAndData = nil userOp.Signature = nil res, byteres, err := packUserOp(userOp) - + shouldEqualStr := "000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" assert.NoError(t, err) + if shouldEqualStr != res { + fmt.Println("not equal") + } fmt.Println(res) + fmt.Println(shouldEqualStr) fmt.Println(byteres) } func TestUserOpHash(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOpHash, err := UserOpHash(userOp, strategy, big.NewInt(1), big.NewInt(2)) + userOpHash, userOpHashStr, err := UserOpHash(userOp, strategy, big.NewInt(0xffffffffff), big.NewInt(0xaa)) assert.NoError(t, err) + shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000e99c4db5e360b8c84bf3660393cb2a85c3029b440000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000ffffffffff00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + fmt.Println(userOpHashStr) + fmt.Println(shouldEqualStr) fmt.Println(hex.EncodeToString(userOpHash)) } @@ -94,3 +103,42 @@ func TestGenerateTestPaymaterDataparse(t *testing.T) { //} //str := "0x } +func TestDemo(t *testing.T) { + //strategy := dashboard_service.GetStrategyById("1") + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + + //str := "0x" + //fmt.Println(len(str)) + //fmt.Println(str[:2]) + //fmt.Println(str[:2] != + bytesTy, err := abi.NewType("bytes", "", nil) + //uint256Ty, err := abi.NewType("uint256", "", nil) + if err != nil { + fmt.Println(err) + } + uint256Ty, _ := abi.NewType("uint256", "", nil) + if err != nil { + fmt.Println(err) + } + addressTy, _ := abi.NewType("address", "", nil) + arguments := abi.Arguments{ + { + Type: bytesTy, + }, + { + Type: uint256Ty, + }, + { + Type: addressTy, + }, + } + packUserOpStr, _, err := packUserOp(userOp) + //Btypelen := len(packUserOpStrByte) + //byteArray := [Btypelen]byte(packUserOpStrByte) + strByte, _ := hex.DecodeString(packUserOpStr) + bytesRes, err := arguments.Pack(strByte, big.NewInt(1), common.Address{}) + if err != nil { + fmt.Println(err) + } + fmt.Println(hex.EncodeToString(bytesRes)) +} From 8624b27526a6153c996050a6de41fa70b46bc80a Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 20 Mar 2024 22:40:53 +0800 Subject: [PATCH 35/47] fix packOp bug --- common/model/user_operation.go | 16 +++--- common/utils/util.go | 2 +- .../dashboard_service/dashboard_service.go | 4 +- service/operator/try_pay_user_op_execute.go | 53 +++++++++++-------- .../operator/try_pay_user_op_execute_test.go | 10 ++-- 5 files changed, 46 insertions(+), 39 deletions(-) diff --git a/common/model/user_operation.go b/common/model/user_operation.go index 33027aea..aed85ce3 100644 --- a/common/model/user_operation.go +++ b/common/model/user_operation.go @@ -23,15 +23,15 @@ var ( 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:"init_code" mapstructure:"init_code" ` - CallData []byte `json:"call_data" mapstructure:"call_data" binding:"required"` - CallGasLimit *big.Int `json:"call_gas_limit" mapstructure:"call_gas_limit" binding:"required"` - VerificationGasLimit *big.Int `json:"verification_gas_limit" mapstructure:"verification_gas_limit" binding:"required"` - PreVerificationGas *big.Int `json:"pre_verification_gas" mapstructure:"pre_verification_gas" binding:"required"` - MaxFeePerGas *big.Int `json:"max_fee_per_gas" mapstructure:"max_fee_per_gas" binding:"required"` - MaxPriorityFeePerGas *big.Int `json:"max_priority_fee_per_gas" mapstructure:"max_priority_fee_per_gas" binding:"required"` + InitCode []byte `json:"initCode" mapstructure:"init_code" ` + CallData []byte `json:"callData" mapstructure:"call_data" binding:"required"` + CallGasLimit *big.Int `json:"callGasLimit" mapstructure:"call_gas_limit" binding:"required"` + VerificationGasLimit *big.Int `json:"verificationGasLimit" mapstructure:"verification_gas_limit" binding:"required"` + PreVerificationGas *big.Int `json:"preVerificationGas" mapstructure:"pre_verification_gas" binding:"required"` + MaxFeePerGas *big.Int `json:"maxFeePerGas" mapstructure:"max_fee_per_gas" binding:"required"` + MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas" mapstructure:"max_priority_fee_per_gas" binding:"required"` + PaymasterAndData []byte `json:"paymasterAndData" mapstructure:"paymaster_and_data"` Signature []byte `json:"signature" mapstructure:"signature" binding:"required"` - PaymasterAndData []byte `json:"paymaster_and_data" mapstructure:"paymaster_and_data"` } type UserOperationSimple struct { Sender []byte `json:"sender" mapstructure:"sender" binding:"required,hexParam"` diff --git a/common/utils/util.go b/common/utils/util.go index 06957105..a317c596 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -24,7 +24,7 @@ func GenerateMockUserOperation() *map[string]any { "sender": "0xF8498599744BC37e141cb800B67Dbf103a6b5881", "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", "verification_gas_limit": "0x05fa35", - "paymaster_and_data": "0x0000000000325602a77416A16136FDafd04b299f", + "paymaster_and_data": "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200", } return &MockUserOpData diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 71eef4a7..5fb5c85c 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -15,7 +15,7 @@ func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b44", + PayMasterAddress: "0xd93349Ee959d295B115Ee223aF10EF432A8E8523", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, EntryPointTag: types.EntrypointV06, @@ -24,7 +24,7 @@ func init() { MockStrategyMap["2"] = &model.Strategy{ Id: "2", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b44", + PayMasterAddress: "0xd93349Ee959d295B115Ee223aF10EF432A8E8523", PayType: types.PayTypeERC20, EntryPointTag: types.EntrypointV06, NetWork: types.Sepolia, diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index b40e6e4a..524ee0d0 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -19,7 +19,6 @@ import ( "math/big" "strconv" "strings" - "time" ) func TryPayUserOpExecute(request *model.TryPayUserOpRequest) (*model.TryPayUserOpResponse, error) { @@ -140,57 +139,57 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { "components": [ { "internalType": "address", - "name": "sender", + "name": "Sender", "type": "address" }, { "internalType": "uint256", - "name": "nonce", + "name": "Nonce", "type": "uint256" }, { "internalType": "bytes", - "name": "initCode", + "name": "InitCode", "type": "bytes" }, { "internalType": "bytes", - "name": "callData", + "name": "CallData", "type": "bytes" }, { "internalType": "uint256", - "name": "callGasLimit", + "name": "CallGasLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "verificationGasLimit", + "name": "VerificationGasLimit", "type": "uint256" }, { "internalType": "uint256", - "name": "preVerificationGas", + "name": "PreVerificationGas", "type": "uint256" }, { "internalType": "uint256", - "name": "maxFeePerGas", + "name": "MaxFeePerGas", "type": "uint256" }, { "internalType": "uint256", - "name": "maxPriorityFeePerGas", + "name": "MaxPriorityFeePerGas", "type": "uint256" }, { "internalType": "bytes", - "name": "paymasterAndData", + "name": "PaymasterAndData", "type": "bytes" }, { "internalType": "bytes", - "name": "signature", + "name": "Signature", "type": "bytes" } ], @@ -215,14 +214,24 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { return "", nil, err } //https://github.com/jayden-sudo/SoulWalletCore/blob/dc76bdb9a156d4f99ef41109c59ab99106c193ac/contracts/utils/CalldataPack.sol#L51-L65 - hexString := hex.EncodeToString(encoded) + //1. 从 63*10+ 1 ~64*10获取 hexString = hexString[64:] - hexLen := len(hexString) - hexString = hexString[:hexLen-128] + //hexLen := len(hexString) + subIndex := GetIndex(hexString) + hexString = hexString[:subIndex] + //fmt.Printf("subIndex: %d\n", subIndex) return hexString, encoded, nil } +func GetIndex(hexString string) int64 { + //1. 从 63*10+ 1 ~64*10获取 + + indexPre := hexString[576:640] + indePreInt, _ := strconv.ParseInt(indexPre, 16, 64) + result := indePreInt * 2 + return result +} func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStart *big.Int, validEnd *big.Int) ([]byte, string, error) { packUserOpStr, _, err := packUserOp(userOp) @@ -311,13 +320,15 @@ func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validS return signature, err } +// 1710044496 +// 1741580496 func getValidTime() (string, string) { - currentTime := time.Now() - currentTimestamp := currentTime.Unix() - futureTime := currentTime.Add(15 * time.Minute) - futureTimestamp := futureTime.Unix() - currentTimestampStr := strconv.FormatInt(currentTimestamp, 10) - futureTimestampStr := strconv.FormatInt(futureTimestamp, 10) + //currentTime := time.Nsow() + //currentTimestamp := 1710044496 + //futureTime := currentTime.Add(15 * time.Minute) + //futureTimestamp := futureTime.Unix() + currentTimestampStr := strconv.FormatInt(1710044496, 10) + futureTimestampStr := strconv.FormatInt(1741580496, 10) currentTimestampStrSupply := SupplyZero(currentTimestampStr, 64) futureTimestampStrSupply := SupplyZero(futureTimestampStr, 64) return currentTimestampStrSupply, futureTimestampStrSupply diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 15e0db92..f6476d64 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -40,14 +40,10 @@ func TestGenerateTestData(t *testing.T) { } func TestPackUserOp(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOp.PaymasterAndData = nil - userOp.Signature = nil res, byteres, err := packUserOp(userOp) - shouldEqualStr := "000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + shouldEqualStr := "000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" assert.NoError(t, err) - if shouldEqualStr != res { - fmt.Println("not equal") - } + assert.EqualValues(t, shouldEqualStr, res) fmt.Println(res) fmt.Println(shouldEqualStr) fmt.Println(byteres) @@ -56,7 +52,7 @@ func TestPackUserOp(t *testing.T) { func TestUserOpHash(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOpHash, userOpHashStr, err := UserOpHash(userOp, strategy, big.NewInt(0xffffffffff), big.NewInt(0xaa)) + userOpHash, userOpHashStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) assert.NoError(t, err) shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000e99c4db5e360b8c84bf3660393cb2a85c3029b440000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000ffffffffff00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" fmt.Println(userOpHashStr) From ee3bb14c5be1156b00f11016f3d3bcf28eb30e2d Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 20 Mar 2024 23:07:44 +0800 Subject: [PATCH 36/47] fix packOp bug --- service/operator/try_pay_user_op_execute.go | 5 +++-- service/operator/try_pay_user_op_execute_test.go | 13 +++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 524ee0d0..7ac745bb 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -247,6 +247,7 @@ func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStar if err != nil { fmt.Println(err) } + uint48Ty, err := abi.NewType("uint48", "", nil) addressTy, _ := abi.NewType("address", "", nil) arguments := abi.Arguments{ @@ -263,10 +264,10 @@ func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStar Type: uint256Ty, }, { - Type: uint256Ty, + Type: uint48Ty, }, { - Type: uint256Ty, + Type: uint48Ty, }, } chainId, err := chain_service.GetChainId(strategy.NetWork) diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index f6476d64..eea5b68d 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -39,6 +39,7 @@ func TestGenerateTestData(t *testing.T) { fmt.Println(len(signature)) } func TestPackUserOp(t *testing.T) { + // give same len signuature and paymasteranddata userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) res, byteres, err := packUserOp(userOp) shouldEqualStr := "000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" @@ -52,12 +53,16 @@ func TestPackUserOp(t *testing.T) { func TestUserOpHash(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOpHash, userOpHashStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) + userOpHash, userOpabiEncodeStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) assert.NoError(t, err) - shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000e99c4db5e360b8c84bf3660393cb2a85c3029b440000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000ffffffffff00000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - fmt.Println(userOpHashStr) + shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + fmt.Println(userOpabiEncodeStr) fmt.Println(shouldEqualStr) - fmt.Println(hex.EncodeToString(userOpHash)) + assert.EqualValues(t, userOpabiEncodeStr, shouldEqualStr) + userOpHashStr := hex.EncodeToString(userOpHash) + fmt.Println(userOpHashStr) + shouldEqualHashStr := "a1e2c52ad5779f4eb7a87c570149d7d33614fbc1d1ac30fa6cfe80107909e0fa" + assert.EqualValues(t, userOpHashStr, shouldEqualHashStr) } func TestUserOP(t *testing.T) { From 5e19e9a049dcafb58d6c077a6a1bcfe59024965b Mon Sep 17 00:00:00 2001 From: dylanyang Date: Wed, 20 Mar 2024 23:12:23 +0800 Subject: [PATCH 37/47] fix packOp bug --- service/operator/try_pay_user_op_execute.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 7ac745bb..fe6e81ce 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -208,6 +208,8 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { return "", nil, err } method := abiEncoder.Methods["UserOp"] + //TODO disgusting logic + userOp.PaymasterAndData = []byte("0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200") encoded, err := method.Inputs.Pack(userOp) if err != nil { From 9a515d5d5e7ac0271658c86249c9d92d2e83a730 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 21 Mar 2024 13:06:50 +0800 Subject: [PATCH 38/47] fix packOp bug --- service/operator/try_pay_user_op_execute.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index fe6e81ce..24734137 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -209,7 +209,11 @@ func packUserOp(userOp *model.UserOperation) (string, []byte, error) { } method := abiEncoder.Methods["UserOp"] //TODO disgusting logic - userOp.PaymasterAndData = []byte("0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200") + + paymasterDataTmp, err := hex.DecodeString("d93349Ee959d295B115Ee223aF10EF432A8E8523000000000000000000000000000000000000000000000000000000001710044496000000000000000000000000000000000000000000000000000000174158049605bea0bfb8539016420e76749fda407b74d3d35c539927a45000156335643827672fa359ee968d72db12d4b4768e8323cd47443505ab138a525c1f61c6abdac501") + //fmt.Printf("paymasterDataTmpLen: %x\n", len(paymasterDataTmp)) + //fmt.Printf("paymasterDataKLen : %x\n", len(userOp.PaymasterAndData)) + userOp.PaymasterAndData = paymasterDataTmp encoded, err := method.Inputs.Pack(userOp) if err != nil { @@ -297,7 +301,8 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat //validationGas := userOp.VerificationGasLimit.String() //postOPGas := userOp.CallGasLimit.String() validStart, validEnd := getValidTime() - message := fmt.Sprintf("%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart+validEnd) + //fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) + message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart, validEnd) signatureByte, err := SignPaymaster(userOp, strategy, validStart, validEnd) if err != nil { return "", "", err From f5437848669c59334968e44f7c4f72d3ac19296f Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 21 Mar 2024 20:15:20 +0800 Subject: [PATCH 39/47] fix sign bug --- common/utils/util.go | 21 ++++++- service/operator/try_pay_user_op_execute.go | 37 ++++++++--- .../operator/try_pay_user_op_execute_test.go | 62 ++++++++++++++++++- 3 files changed, 106 insertions(+), 14 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index a317c596..8ee92dfc 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -2,6 +2,7 @@ package utils import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "bytes" "encoding/hex" "encoding/json" "github.com/ethereum/go-ethereum/crypto" @@ -16,12 +17,12 @@ func GenerateMockUserOperation() *map[string]any { var MockUserOpData = map[string]any{ "call_data": "0xb61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", "call_gas_limit": "0x54fa", - "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000", - "max_fee_per_gas": "0x2aa887baca", + "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000", + "max_fee_per_gas": "0x59682f8e", "max_priority_fee_per_gas": "0x59682f00", "nonce": "0x00", "pre_verification_gas": "0xae64", - "sender": "0xF8498599744BC37e141cb800B67Dbf103a6b5881", + "sender": "0xFfDB071C2b58CCC10Ad386f9Bb4E8d3d664CE73c", "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", "verification_gas_limit": "0x05fa35", "paymaster_and_data": "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200", @@ -85,3 +86,17 @@ func SignMessage(privateKeyHex string, message string) ([]byte, error) { return signature, nil } + +func ToEthSignedMessageHash(msg []byte) []byte { + buffer := new(bytes.Buffer) + buffer.Write([]byte("\x19Ethereum Signed Message:\n32")) + buffer.Write(msg) + return crypto.Keccak256(buffer.Bytes()) +} + +func ReplaceLastTwoChars(str, replacement string) string { + if len(str) < 2 { + return str + } + return str[:len(str)-2] + replacement +} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 24734137..e7ab2534 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -286,8 +286,8 @@ func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStar if err != nil { return nil, "", err } - encodeHash := crypto.Keccak256Hash(bytesRes) - return encodeHash.Bytes(), hex.EncodeToString(bytesRes), nil + encodeHash := crypto.Keccak256(bytesRes) + return encodeHash, hex.EncodeToString(bytesRes), nil } @@ -303,7 +303,7 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat validStart, validEnd := getValidTime() //fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart, validEnd) - signatureByte, err := SignPaymaster(userOp, strategy, validStart, validEnd) + signatureByte, _, err := SignPaymaster(userOp, strategy, validStart, validEnd) if err != nil { return "", "", err } @@ -312,20 +312,41 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat return message, signatureStr, nil } -func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, error) { +func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, []byte, error) { //string to int validStartInt, _ := strconv.ParseInt(validStart, 10, 64) validEndInt, _ := strconv.ParseInt(validEnd, 10, 64) userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(validStartInt), big.NewInt(validEndInt)) + hashToEthSignHash := utils.ToEthSignedMessageHash(userOpHash) + fmt.Printf("userOpHashStr: %s\n", hex.EncodeToString(userOpHash)) + fmt.Printf("hashToEthSignHashStr: %s\n", hex.EncodeToString(hashToEthSignHash)) if err != nil { - return nil, err + return nil, nil, err } privateKey, err := crypto.HexToECDSA("1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421") if err != nil { - return nil, err + return nil, nil, err } - signature, err := crypto.Sign(userOpHash, privateKey) - return signature, err + + signature, err := crypto.Sign(hashToEthSignHash, privateKey) + + signatureStr := hex.EncodeToString(signature) + var signatureAfterProcess string + + if strings.HasSuffix(signatureStr, "00") { + signatureAfterProcess = utils.ReplaceLastTwoChars(signatureStr, "1b") + } else if strings.HasSuffix(signatureStr, "01") { + signatureAfterProcess = utils.ReplaceLastTwoChars(signatureStr, "1c") + } else { + signatureAfterProcess = signatureStr + } + + signatureAfterProcessByte, err := hex.DecodeString(signatureAfterProcess) + if err != nil { + return nil, nil, err + } + + return signatureAfterProcessByte, userOpHash, err } // 1710044496 diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index eea5b68d..301ea646 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -4,11 +4,13 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "crypto/ecdsa" "encoding/hex" "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "math/big" "testing" @@ -42,27 +44,81 @@ func TestPackUserOp(t *testing.T) { // give same len signuature and paymasteranddata userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) res, byteres, err := packUserOp(userOp) - shouldEqualStr := "000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + shouldEqualStr := "000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000000059682f8e0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" assert.NoError(t, err) assert.EqualValues(t, shouldEqualStr, res) fmt.Println(res) fmt.Println(shouldEqualStr) fmt.Println(byteres) } +func TestSignPaymaster(t *testing.T) { + + userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) + strategy := dashboard_service.GetStrategyById("1") + + validStart, validEnd := getValidTime() + + //fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) + //message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart, validEnd) + signatureByte, hashByte, err := SignPaymaster(userOp, strategy, validStart, validEnd) + //signatureStr := hex.EncodeToString(signatureByte) + assert.NoError(t, err) + + signatureStr := hex.EncodeToString(signatureByte) + hashByteStr := hex.EncodeToString(hashByte) + fmt.Printf("signatureStr len: %s\n", signatureStr) + fmt.Printf("hashByteStr len: %s\n", hashByteStr) + + sig, err := crypto.HexToECDSA(signatureStr) + if err != nil { + assert.NoError(t, err) + return + } + + publicKey := sig.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + assert.Error(t, err) + return + } + address := crypto.PubkeyToAddress(*publicKeyECDSA) + fmt.Printf("address: %s\n", address.Hex()) + //sigPublicKey, err := crypto.Ecrecover(hashToEthSignHash, signatureByte) + //fmt.Println(sigPublicKey) + //sigPublicKeyStr := hex.EncodeToString(sigPublicKey) + //fmt.Println(sigPublicKeyStr) + //assert.Equal(t, sigPublicKeyStr, "044eaed6b1f16e60354156fa334a094affc76d7b7061875a0b04290af9a14cc14ce2bce6ceba941856bd55c63f8199f408fff6495ce9d4c76899055972d23bdb3e") + // + //pubKeyBytes, _ := hex.DecodeString("044eaed6b1f16e60354156fa334a094affc76d7b7061875a0b04290af9a14cc14ce2bce6ceba941856bd55c63f8199f408fff6495ce9d4c76899055972d23bdb3e") + //signatureNoRecoverID := signatureByte[:len(signatureByte)-1] + //verified := crypto.VerifySignature(pubKeyBytes, hashToEthSignHash, signatureNoRecoverID) + //assert.True(t, verified) + +} + +func TestSign(t *testing.T) { + //hash 3244304e46b095a6dc5ff8af5cac03cbb22f6e07d3a0841dc4b3b8bc399a44702724cc7aad26b3854545269e34c156565f717b96acc52ee9de95526c644ddf6d00 + //sign 9429db04bd812b79bf15d55ee271426894cbfb6e7431da8d934d5e970dbf992c + // address +} func TestUserOpHash(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) userOpHash, userOpabiEncodeStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) assert.NoError(t, err) - shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000f8498599744bc37e141cb800b67dbf103a6b58810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000002aa887baca0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000340966abb6e37a06014546e0542b3aafad4550810000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000000059682f8e0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" fmt.Println(userOpabiEncodeStr) fmt.Println(shouldEqualStr) + assert.EqualValues(t, userOpabiEncodeStr, shouldEqualStr) + fmt.Println("finish euqal abiencode") userOpHashStr := hex.EncodeToString(userOpHash) fmt.Println(userOpHashStr) - shouldEqualHashStr := "a1e2c52ad5779f4eb7a87c570149d7d33614fbc1d1ac30fa6cfe80107909e0fa" + shouldEqualHashStr := "9429db04bd812b79bf15d55ee271426894cbfb6e7431da8d934d5e970dbf992c" assert.EqualValues(t, userOpHashStr, shouldEqualHashStr) + fmt.Println(userOpHashStr) + fmt.Println(shouldEqualHashStr) } func TestUserOP(t *testing.T) { From 306a3f3741c28bf4284abe07d70fc5f84687de57 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 11:52:45 +0800 Subject: [PATCH 40/47] fix sign bug --- common/utils/util.go | 2 +- service/operator/try_pay_user_op_execute.go | 4 +- .../operator/try_pay_user_op_execute_test.go | 43 +++++++++++-------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 8ee92dfc..788e0366 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -18,7 +18,7 @@ func GenerateMockUserOperation() *map[string]any { "call_data": "0xb61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", "call_gas_limit": "0x54fa", "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000", - "max_fee_per_gas": "0x59682f8e", + "max_fee_per_gas": "0x59682fb0", "max_priority_fee_per_gas": "0x59682f00", "nonce": "0x00", "pre_verification_gas": "0xae64", diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index e7ab2534..c5e778dc 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -356,8 +356,8 @@ func getValidTime() (string, string) { //currentTimestamp := 1710044496 //futureTime := currentTime.Add(15 * time.Minute) //futureTimestamp := futureTime.Unix() - currentTimestampStr := strconv.FormatInt(1710044496, 10) - futureTimestampStr := strconv.FormatInt(1741580496, 10) + currentTimestampStr := strconv.FormatInt(1710044496, 16) + futureTimestampStr := strconv.FormatInt(1741580496, 16) currentTimestampStrSupply := SupplyZero(currentTimestampStr, 64) futureTimestampStrSupply := SupplyZero(futureTimestampStr, 64) return currentTimestampStrSupply, futureTimestampStrSupply diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 301ea646..5541c806 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -4,13 +4,11 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" - "crypto/ecdsa" "encoding/hex" "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "math/big" "testing" @@ -51,6 +49,10 @@ func TestPackUserOp(t *testing.T) { fmt.Println(shouldEqualStr) fmt.Println(byteres) } +func TestGetValidTime(t *testing.T) { + validStart, validEnd := getValidTime() + fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) +} func TestSignPaymaster(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) @@ -68,21 +70,21 @@ func TestSignPaymaster(t *testing.T) { hashByteStr := hex.EncodeToString(hashByte) fmt.Printf("signatureStr len: %s\n", signatureStr) fmt.Printf("hashByteStr len: %s\n", hashByteStr) - - sig, err := crypto.HexToECDSA(signatureStr) - if err != nil { - assert.NoError(t, err) - return - } - - publicKey := sig.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - assert.Error(t, err) - return - } - address := crypto.PubkeyToAddress(*publicKeyECDSA) - fmt.Printf("address: %s\n", address.Hex()) + // + //sigPublicKey, err := crypto.Ecrecover(hashByte, signatureByte) + //if err != nil { + // assert.NoError(t, err) + // return + //} + //sigPublicKeyStr := hex.EncodeToString(sigPublicKey) + //fmt.Println(sigPublicKeyStr) + //publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + //if !ok { + // assert.Error(t, err) + // return + //} + //address := crypto.PubkeyToAddress(*publicKeyECDSA) + //fmt.Printf("address: %s\n", address.Hex()) //sigPublicKey, err := crypto.Ecrecover(hashToEthSignHash, signatureByte) //fmt.Println(sigPublicKey) //sigPublicKeyStr := hex.EncodeToString(sigPublicKey) @@ -107,15 +109,18 @@ func TestUserOpHash(t *testing.T) { userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) userOpHash, userOpabiEncodeStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) assert.NoError(t, err) - shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000000059682f8e0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000000059682fb00000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" fmt.Println(userOpabiEncodeStr) fmt.Println(shouldEqualStr) assert.EqualValues(t, userOpabiEncodeStr, shouldEqualStr) + if userOpabiEncodeStr != shouldEqualStr { + return + } fmt.Println("finish euqal abiencode") userOpHashStr := hex.EncodeToString(userOpHash) fmt.Println(userOpHashStr) - shouldEqualHashStr := "9429db04bd812b79bf15d55ee271426894cbfb6e7431da8d934d5e970dbf992c" + shouldEqualHashStr := "8ad4946fb4665c29754b83495e796fa03013aaa0f194326afad73ce2fc5b91e9" assert.EqualValues(t, userOpHashStr, shouldEqualHashStr) fmt.Println(userOpHashStr) fmt.Println(shouldEqualHashStr) From 183935100b007c5d0a1ed51d7e1ade4c19fbb30b Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 13:13:19 +0800 Subject: [PATCH 41/47] fix sign bug --- common/utils/util.go | 6 +- service/operator/try_pay_user_op_execute.go | 4 ++ .../operator/try_pay_user_op_execute_test.go | 61 ++++++++++++++++--- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 788e0366..257b37d7 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -18,12 +18,12 @@ func GenerateMockUserOperation() *map[string]any { "call_data": "0xb61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", "call_gas_limit": "0x54fa", "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000", - "max_fee_per_gas": "0x59682fb0", + "max_fee_per_gas": "0x5968334e", "max_priority_fee_per_gas": "0x59682f00", "nonce": "0x00", "pre_verification_gas": "0xae64", - "sender": "0xFfDB071C2b58CCC10Ad386f9Bb4E8d3d664CE73c", - "signature": "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", + "sender": "0xffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c", + "signature": "0xe0a9eca60d705c9bfa6a91d794cf9c3e00058892f42f16ea55105086b23be1726457daf05b32290789d357b2ba042ce4564dba690d5e4c2211ca11c300de94d21c", "verification_gas_limit": "0x05fa35", "paymaster_and_data": "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200", } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index c5e778dc..6cf418e6 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -286,6 +286,10 @@ func UserOpHash(userOp *model.UserOperation, strategy *model.Strategy, validStar if err != nil { return nil, "", err } + //bytesResStr := hex.EncodeToString(bytesRes) + //fmt.Printf("bytesResStr: %s\n", bytesResStr) + //fmt.Printf("bytesRes: %x\n", bytesRes) + encodeHash := crypto.Keccak256(bytesRes) return encodeHash, hex.EncodeToString(bytesRes), nil diff --git a/service/operator/try_pay_user_op_execute_test.go b/service/operator/try_pay_user_op_execute_test.go index 5541c806..56dc7225 100644 --- a/service/operator/try_pay_user_op_execute_test.go +++ b/service/operator/try_pay_user_op_execute_test.go @@ -4,13 +4,16 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "bytes" "encoding/hex" "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "math/big" + "strconv" "testing" ) @@ -49,6 +52,10 @@ func TestPackUserOp(t *testing.T) { fmt.Println(shouldEqualStr) fmt.Println(byteres) } +func TestConvertHex(t *testing.T) { + hexString := strconv.FormatUint(1500000000, 16) + fmt.Println(hexString) +} func TestGetValidTime(t *testing.T) { validStart, validEnd := getValidTime() fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) @@ -107,23 +114,57 @@ func TestSign(t *testing.T) { func TestUserOpHash(t *testing.T) { strategy := dashboard_service.GetStrategyById("1") userOp, _ := model.NewUserOp(utils.GenerateMockUserOperation()) - userOpHash, userOpabiEncodeStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) + encodeHash, userOpabiEncodeStr, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) assert.NoError(t, err) - shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae640000000000000000000000000000000000000000000000000000000059682fb00000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - fmt.Println(userOpabiEncodeStr) + shouldEqualStr := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae64000000000000000000000000000000000000000000000000000000005968334e0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + fmt.Printf("userOpabiEncodeStr %s \n", userOpabiEncodeStr) + fmt.Printf("encodeHash %s \n", hex.EncodeToString(encodeHash)) + fmt.Println(shouldEqualStr) assert.EqualValues(t, userOpabiEncodeStr, shouldEqualStr) if userOpabiEncodeStr != shouldEqualStr { return } - fmt.Println("finish euqal abiencode") - userOpHashStr := hex.EncodeToString(userOpHash) - fmt.Println(userOpHashStr) - shouldEqualHashStr := "8ad4946fb4665c29754b83495e796fa03013aaa0f194326afad73ce2fc5b91e9" - assert.EqualValues(t, userOpHashStr, shouldEqualHashStr) - fmt.Println(userOpHashStr) - fmt.Println(shouldEqualHashStr) + //fmt.Println("finish euqal abiencode") + //userOpHashStr := hex.EncodeToString(userOpHash) + //fmt.Println(userOpHashStr) + //shouldEqualHashStr := "8ad4946fb4665c29754b83495e796fa03013aaa0f194326afad73ce2fc5b91e9" + //assert.EqualValues(t, userOpHashStr, shouldEqualHashStr) + //fmt.Println(userOpHashStr) + //fmt.Println(shouldEqualHashStr) +} +func TestKeccak256(t *testing.T) { + str := "00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000aa36a7000000000000000000000000d93349ee959d295b115ee223af10ef432a8e852300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000ffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000054fa000000000000000000000000000000000000000000000000000000000005fa35000000000000000000000000000000000000000000000000000000000000ae64000000000000000000000000000000000000000000000000000000005968334e0000000000000000000000000000000000000000000000000000000059682f00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000589406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + //decimal, err := strconv.ParseInt(str, 16, 64) + //if err != nil { + // fmt.Println(err) + // return + //} + //fmt.Println(decimal) + strByte, err := hex.DecodeString(str) + if err != nil { + fmt.Printf("has error %s", err) + return + } + fmt.Println(strByte) + //strConvert := hex.EncodeToString(strByte) + //fmt.Println(strConvert) + //fmt.Println(strConvert) + res := crypto.Keccak256(strByte) + fmt.Println(hex.EncodeToString(res)) + + //resHash := crypto.Keccak256Hash(strByte) + //fmt.Println(resHash.Hex()) + //msg := []byte("abc") + //exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") + //checkhash(t, "Sha3-256-array", func(in []byte) []byte { h :=cry; return h[:] }, msg, exp) +} +func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) { + sum := f(msg) + if !bytes.Equal(exp, sum) { + t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum) + } } func TestUserOP(t *testing.T) { From 2e8da134503b1c44e50c3a81080a3802f8b1f292 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 13:56:43 +0800 Subject: [PATCH 42/47] fix sign bug --- common/utils/util.go | 6 +++--- common/utils/util_test.go | 11 +++++++++++ service/operator/try_pay_user_op_execute.go | 5 ++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 257b37d7..3913a14a 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -18,14 +18,14 @@ func GenerateMockUserOperation() *map[string]any { "call_data": "0xb61d27f60000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000000000000000325602a77416a16136fdafd04b299fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000", "call_gas_limit": "0x54fa", "init_code": "0x9406cc6185a346906296840746125a0e449764545fbfb9cf000000000000000000000000b6bcf9517d193f551d0e3d6860103972dd13de7b0000000000000000000000000000000000000000000000000000000000000000", - "max_fee_per_gas": "0x5968334e", + "max_fee_per_gas": "0x5968606e", "max_priority_fee_per_gas": "0x59682f00", "nonce": "0x00", "pre_verification_gas": "0xae64", "sender": "0xffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c", - "signature": "0xe0a9eca60d705c9bfa6a91d794cf9c3e00058892f42f16ea55105086b23be1726457daf05b32290789d357b2ba042ce4564dba690d5e4c2211ca11c300de94d21c", + "signature": "0xaa846693598194980f3bf50486be854704534c1622d0c2ee895a5a1ebe1508221909a27cc7971d9f522c8df13b9d8a6ee446d09ea7635f31c59d77d35d1281421c", "verification_gas_limit": "0x05fa35", - "paymaster_and_data": "0xE99c4Db5E360B8c84bF3660393CB2A85c3029b4400000000000000000000000000000000000000000000000000000000171004449600000000000000000000000000000000000000000000000000000017415804969e46721fc1938ac427add8a9e0d5cba2be5b17ccda9b300d0d3eeaff1904dfc23e276abd1ba6e3e269ec6aa36fe6a2442c18d167b53d7f9f0d1b3ebe80b09a6200", + "paymaster_and_data": "0xd93349Ee959d295B115Ee223aF10EF432A8E8523000000000000000000000000000000000000000000000000000000000065ed35500000000000000000000000000000000000000000000000000000000067ce68d015fdcf36211b7269133323a60a4b783a6a91ff72f1c5ad31398e259b9be5bb980d1a07b3aaee9a1c3f4bcc37c64bbf3e86da1b30227ca7d737b940caef5778191b", } return &MockUserOpData diff --git a/common/utils/util_test.go b/common/utils/util_test.go index b65aa0e5..583a7cd0 100644 --- a/common/utils/util_test.go +++ b/common/utils/util_test.go @@ -46,6 +46,17 @@ func TestNewUserOp(t *testing.T) { fmt.Printf("userOp: %s\n", hex.EncodeToString(userOp.InitCode)) } +func TestToEthSignedMessageHash(t *testing.T) { + strByte, err := hex.DecodeString("4bd85fb8854a6bd9dfb18cf88a5bba4daf9bc65f4b8ac00a706f426d40498302") + if err != nil { + fmt.Printf("has Error %s", err) + return + } + afterStrByte := ToEthSignedMessageHash(strByte) + fmt.Printf("afterStrByte: %x\n", afterStrByte) + afterStr := hex.EncodeToString(afterStrByte) + fmt.Printf("afterStr: %s\n", afterStr) +} func TestValidate(t *testing.T) { //userOp := GenerateMockUserOperation() diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 6cf418e6..44975053 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -318,9 +318,8 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, []byte, error) { //string to int - validStartInt, _ := strconv.ParseInt(validStart, 10, 64) - validEndInt, _ := strconv.ParseInt(validEnd, 10, 64) - userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(validStartInt), big.NewInt(validEndInt)) + + userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) hashToEthSignHash := utils.ToEthSignedMessageHash(userOpHash) fmt.Printf("userOpHashStr: %s\n", hex.EncodeToString(userOpHash)) fmt.Printf("hashToEthSignHashStr: %s\n", hex.EncodeToString(hashToEthSignHash)) From db26616189e18d8c058c1f45526f0d4e7158652a Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 14:01:28 +0800 Subject: [PATCH 43/47] fix sign bug --- service/operator/try_pay_user_op_execute.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 44975053..e9a05d10 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -318,8 +318,8 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, []byte, error) { //string to int - - userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1741580496)) + //TODO + userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1820044496)) hashToEthSignHash := utils.ToEthSignedMessageHash(userOpHash) fmt.Printf("userOpHashStr: %s\n", hex.EncodeToString(userOpHash)) fmt.Printf("hashToEthSignHashStr: %s\n", hex.EncodeToString(hashToEthSignHash)) @@ -360,7 +360,7 @@ func getValidTime() (string, string) { //futureTime := currentTime.Add(15 * time.Minute) //futureTimestamp := futureTime.Unix() currentTimestampStr := strconv.FormatInt(1710044496, 16) - futureTimestampStr := strconv.FormatInt(1741580496, 16) + futureTimestampStr := strconv.FormatInt(1820044496, 16) currentTimestampStrSupply := SupplyZero(currentTimestampStr, 64) futureTimestampStrSupply := SupplyZero(futureTimestampStr, 64) return currentTimestampStrSupply, futureTimestampStrSupply From 7aac1e0814cc8b95c267ed853161b9bba9a7454f Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 14:09:23 +0800 Subject: [PATCH 44/47] fix sign bug --- service/operator/try_pay_user_op_execute.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index e9a05d10..16567c68 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -306,7 +306,7 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat //postOPGas := userOp.CallGasLimit.String() validStart, validEnd := getValidTime() //fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) - message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validStart, validEnd) + message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validEnd, validStart) signatureByte, _, err := SignPaymaster(userOp, strategy, validStart, validEnd) if err != nil { return "", "", err @@ -319,7 +319,7 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat func SignPaymaster(userOp *model.UserOperation, strategy *model.Strategy, validStart string, validEnd string) ([]byte, []byte, error) { //string to int //TODO - userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(1710044496), big.NewInt(1820044496)) + userOpHash, _, err := UserOpHash(userOp, strategy, big.NewInt(1820044496), big.NewInt(1710044496)) hashToEthSignHash := utils.ToEthSignedMessageHash(userOpHash) fmt.Printf("userOpHashStr: %s\n", hex.EncodeToString(userOpHash)) fmt.Printf("hashToEthSignHashStr: %s\n", hex.EncodeToString(hashToEthSignHash)) From faf8a789c889bd7f154e944670b0329de9f62808 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 16:24:21 +0800 Subject: [PATCH 45/47] change paymasterAddress --- service/dashboard_service/dashboard_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 5fb5c85c..aa306868 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -15,7 +15,7 @@ func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0xd93349Ee959d295B115Ee223aF10EF432A8E8523", + PayMasterAddress: "0xf196E2916817f8Fc2820c19ef50Fdf47788a5dCD", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, EntryPointTag: types.EntrypointV06, From 0c6b428ff4c824f14d4cfc05a32963431ee1d2f8 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 16:27:08 +0800 Subject: [PATCH 46/47] change paymasterAddress --- service/operator/try_pay_user_op_execute.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 16567c68..43b524be 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -306,7 +306,8 @@ func generatePayMasterAndData(userOp *model.UserOperation, strategy *model.Strat //postOPGas := userOp.CallGasLimit.String() validStart, validEnd := getValidTime() //fmt.Printf("validStart: %s, validEnd: %s\n", validStart, validEnd) - message := fmt.Sprintf("%s%s%s%s", strategy.PayMasterAddress, string(strategy.PayType), validEnd, validStart) + //TODO string(strategy.PayType), + message := fmt.Sprintf("%s%s%s", strategy.PayMasterAddress, validEnd, validStart) signatureByte, _, err := SignPaymaster(userOp, strategy, validStart, validEnd) if err != nil { return "", "", err From 872063590d4870693db29f5d3e5e7e72e5939d92 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 22 Mar 2024 17:18:53 +0800 Subject: [PATCH 47/47] change paymasterAddress --- service/dashboard_service/dashboard_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index aa306868..71ade3bd 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -15,7 +15,7 @@ func init() { MockStrategyMap["1"] = &model.Strategy{ Id: "1", EntryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", - PayMasterAddress: "0xf196E2916817f8Fc2820c19ef50Fdf47788a5dCD", + PayMasterAddress: "0xAEbF4C90b571e7D5cb949790C9b8Dc0280298b63", NetWork: types.Sepolia, PayType: types.PayTypeVerifying, EntryPointTag: types.EntrypointV06,