diff --git a/common/global_const/common_const.go b/common/global_const/common_const.go index fb5b7675..52370b1e 100644 --- a/common/global_const/common_const.go +++ b/common/global_const/common_const.go @@ -22,7 +22,7 @@ const ( ContextKeyApiMoDel = "api_model" StrategyStatusDisable StrategyStatus = "disable" - StrategyStatusAchieve StrategyStatus = "enable" + StrategyStatusAchive StrategyStatus = "enable" ) var ( diff --git a/common/model/api_key_info.go b/common/model/api_key_info.go index a18a33b9..a22daf68 100644 --- a/common/model/api_key_info.go +++ b/common/model/api_key_info.go @@ -3,8 +3,15 @@ package model import "golang.org/x/time/rate" type ApiKeyModel struct { - Disable bool `json:"disable"` - ApiKey string `json:"api_key"` - RateLimit rate.Limit `json:"rate_limit"` - UserId int64 `json:"user_id"` + Disable bool `json:"disable"` + ApiKey string `json:"api_key"` + RateLimit rate.Limit `json:"rate_limit"` + UserId int64 `json:"user_id"` + NetWorkLimitEnable bool `json:"network_limit_enable"` + DomainWhitelist []string `json:"domain_whitelist"` + IPWhiteList []string `json:"ip_white_list"` + PaymasterEnable bool `json:"paymaster_enable"` + Erc20PaymasterEnable bool `json:"erc20_paymaster_enable"` + ProjectSponsorPaymasterEnable bool `json:"project_sponsor_paymaster_enable"` + UserPayPaymasterEnable bool `json:"user_pay_paymaster_enable"` } diff --git a/common/model/env.go b/common/model/env.go index 83444ec6..f553b372 100644 --- a/common/model/env.go +++ b/common/model/env.go @@ -7,6 +7,7 @@ import ( const EnvKey = "Env" const ProdEnv = "prod" const DevEnv = "dev" +const UnitEnv = "unit" type Env struct { Name string // env Name, like `prod`, `dev` and etc., @@ -14,9 +15,11 @@ type Env struct { } func (env *Env) IsDevelopment() bool { - return strings.EqualFold(DevEnv, env.Name) + return strings.EqualFold(DevEnv, env.Name) || strings.EqualFold(UnitEnv, env.Name) +} +func (env *Env) IsUnit() bool { + return strings.EqualFold(UnitEnv, env.Name) } - func (env *Env) IsProduction() bool { return strings.EqualFold(ProdEnv, env.Name) } @@ -24,3 +27,6 @@ func (env *Env) IsProduction() bool { func (env *Env) GetEnvName() *string { return &env.Name } +func (env *Env) SetUnitEnv() { + env.Name = UnitEnv +} diff --git a/common/model/secret_config.go b/common/model/secret_config.go index f00221c3..6bedde15 100644 --- a/common/model/secret_config.go +++ b/common/model/secret_config.go @@ -19,17 +19,15 @@ type SecretConfig struct { RelayDBConfig DBConfig `json:"relay_db_config"` ApiKeyTableName string `json:"api_key_table_name"` StrategyConfigTableName string `json:"strategy_config_table_name"` - FreeSponsorWhitelist []string `json:"free_sponsor_whitelist"` SponsorConfig SponsorConfig `json:"sponsor_config"` } type SponsorConfig struct { - SponsorDepositAddress string `json:"sponsor_deposit_address"` - SponsorDepositPrivateKey string `json:"sponsor_deposit_private_key"` - DashBoardSignerAddress string `json:"dashboard_signer_address"` - DepositTestNetUrl string `json:"deposit_test_net_url"` - DepositMainNetUrl string `json:"deposit_main_net_url"` - SponsorTestClientUrl string `json:"sponsor_client_rpc_test_net"` - SponsorMainClientUrl string `json:"sponsor_client_rpc_main_net"` + SponsorDepositAddress string `json:"sponsor_deposit_address"` + SponsorWithdrawPrivateKey string `json:"sponsor_withdraw_private_key"` + DashBoardSignerAddress string `json:"dashboard_signer_address"` + SponsorTestClientUrl string `json:"sponsor_client_rpc_test_net"` + SponsorMainClientUrl string `json:"sponsor_client_rpc_main_net"` + FreeSponsorWhitelist []string `json:"free_sponsor_whitelist"` } type NetWorkSecretConfig struct { diff --git a/common/model/sponsor.go b/common/model/sponsor.go index 7e4145a0..27f5f81c 100644 --- a/common/model/sponsor.go +++ b/common/model/sponsor.go @@ -1,12 +1,11 @@ package model type DepositSponsorRequest struct { - TimeStamp int64 `json:"time_stamp"` - DepositAddress string `json:"deposit_address"` - TxHash string `json:"tx_hash"` - IsTestNet bool `json:"is_test_net"` - PayUserId string `json:"pay_user_id"` - DepositSource string `json:"deposit_source"` + TimeStamp int64 `json:"time_stamp"` + TxHash string `json:"tx_hash"` + IsTestNet bool `json:"is_test_net"` + PayUserId string `json:"pay_user_id"` + DepositSource string `json:"deposit_source"` } type WithdrawSponsorRequest struct { Amount float64 `json:"amount"` diff --git a/common/network/ethereum_adaptable_executor.go b/common/network/ethereum_adaptable_executor.go index 8a6aab91..56205908 100644 --- a/common/network/ethereum_adaptable_executor.go +++ b/common/network/ethereum_adaptable_executor.go @@ -15,6 +15,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/user_op" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/envirment" "AAStarCommunity/EthPaymaster_BackService/schedulor" "context" "crypto/ecdsa" @@ -96,28 +97,35 @@ func GetEthereumExecutor(network global_const.Network) *EthereumExecutor { if !success { panic(xerrors.Errorf("chainId %s is invalid", config.GetChainId(network))) } - wsUrl := config.GetNewWorkClientURl(network) - wsUrl = strings.Replace(wsUrl, "https", "wss", 1) - webSocketClient, err := ethclient.Dial(wsUrl) - if err != nil { - panic(err) - } - eventListener, err := schedulor.NewEventListener(webSocketClient, network) - if err != nil { - panic(err) - } - go eventListener.Listen() logrus.Debugf("after Lesten network :[%s]", network) geth := gethclient.New(client.Client()) - executorMap[network] = &EthereumExecutor{ - network: network, - Client: client, - ChainId: chainId, - GethClient: geth, - eventListener: eventListener, - webSocketClient: webSocketClient, + ethExecutor := &EthereumExecutor{ + network: network, + Client: client, + ChainId: chainId, + GethClient: geth, + } + + if !envirment.Environment.IsUnit() { + logrus.Infof("Init EventListener network :[%s]", network) + wsUrl := config.GetNewWorkClientURl(network) + wsUrl = strings.Replace(wsUrl, "https", "wss", 1) + logrus.Debugf("wsUrl: %s", wsUrl) + webSocketClient, err := ethclient.Dial(wsUrl) + if err != nil { + panic(err) + } + + eventListener, err := schedulor.NewEventListener(webSocketClient, network) + if err != nil { + panic(err) + } + go eventListener.Listen() + ethExecutor.eventListener = eventListener + ethExecutor.webSocketClient = webSocketClient } + executorMap[network] = ethExecutor return executorMap[network] } @@ -493,7 +501,7 @@ func GetAuth(chainId *big.Int, privateKey *ecdsa.PrivateKey) (*bind.TransactOpts Context: context.Background(), }, nil } -func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, strategy *model.Strategy) ([]byte, string, error) { +func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, strategy *model.Strategy, paymasterDataInput *paymaster_data.PaymasterDataInput) ([]byte, string, error) { version := strategy.GetStrategyEntrypointVersion() erc20Token := common.HexToAddress("0x") payType := strategy.GetPayType() @@ -523,7 +531,7 @@ func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, str } jsonString, _ := json.Marshal(contractUserOp) logrus.Debug("opString :", string(jsonString)) - hash, err := contract.GetHash(&bind.CallOpts{}, contractUserOp, strategy.ExecuteRestriction.EffectiveEndTime, strategy.ExecuteRestriction.EffectiveStartTime, erc20Token, big.NewInt(0)) + hash, err := contract.GetHash(&bind.CallOpts{}, contractUserOp, paymasterDataInput.ValidUntil, paymasterDataInput.ValidAfter, erc20Token, big.NewInt(0)) if err != nil { return nil, "", err } @@ -547,7 +555,7 @@ func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, str jsonString, _ := json.Marshal(packUserOp) logrus.Debug("opString:", string(jsonString)) - hash, err := contract.GetHash(&bind.CallOpts{}, packUserOp, strategy.ExecuteRestriction.EffectiveEndTime, strategy.ExecuteRestriction.EffectiveStartTime, erc20Token, big.NewInt(0)) + hash, err := contract.GetHash(&bind.CallOpts{}, packUserOp, paymasterDataInput.ValidUntil, paymasterDataInput.ValidAfter, erc20Token, big.NewInt(0)) if err != nil { return nil, "", err } @@ -559,7 +567,7 @@ func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, str } func (executor *EthereumExecutor) GetPaymasterData(userOp *user_op.UserOpInput, strategy *model.Strategy, paymasterDataInput *paymaster_data.PaymasterDataInput) (paymasterData []byte, userOpHash []byte, err error) { - userOpHash, _, hashErr := executor.GetUserOpHash(userOp, strategy) + userOpHash, _, hashErr := executor.GetUserOpHash(userOp, strategy, paymasterDataInput) if hashErr != nil { logrus.Errorf("GetUserOpHash error [%v]", err) return nil, nil, err @@ -570,6 +578,9 @@ func (executor *EthereumExecutor) GetPaymasterData(userOp *user_op.UserOpInput, return nil, nil, err } dataGenerateFunc := paymaster_pay_type.GetGenerateFunc(strategy.GetPayType()) + if dataGenerateFunc == nil { + return nil, nil, xerrors.Errorf("payType [%s] not support", strategy.GetPayType()) + } paymasterData, generateDataErr := dataGenerateFunc(paymasterDataInput, signature) if generateDataErr != nil { return nil, nil, generateDataErr diff --git a/common/network/ethereum_adaptable_executor_test.go b/common/network/ethereum_adaptable_executor_test.go index 2012d5e3..a8ee3f10 100644 --- a/common/network/ethereum_adaptable_executor_test.go +++ b/common/network/ethereum_adaptable_executor_test.go @@ -12,6 +12,7 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/common" "github.com/sirupsen/logrus" + "math/big" "testing" "time" ) @@ -267,7 +268,13 @@ func testGetUserOpHash(t *testing.T, input user_op.UserOpInput, strategy *model. input.AccountGasLimits = user_op.DummyAccountGasLimits input.GasFees = user_op.DummyGasFees } - res, _, err := executor.GetUserOpHash(&input, strategy) + now := time.Now() + start := now.Add(-1 * time.Second) + end := now.Add(5 * time.Minute) + res, _, err := executor.GetUserOpHash(&input, strategy, &paymaster_data.PaymasterDataInput{ + ValidUntil: big.NewInt(end.Unix()), + ValidAfter: big.NewInt(start.Unix()), + }) if err != nil { t.Error(err) return diff --git a/common/paymaster_data/paymaster_data.go b/common/paymaster_data/paymaster_data.go index 0a43692f..4d193e00 100644 --- a/common/paymaster_data/paymaster_data.go +++ b/common/paymaster_data/paymaster_data.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/sirupsen/logrus" "math/big" + "time" ) type PaymasterDataInput struct { @@ -22,8 +23,9 @@ type PaymasterDataInput struct { } func NewPaymasterDataInput(strategy *model.Strategy) *PaymasterDataInput { - start := strategy.ExecuteRestriction.EffectiveStartTime - end := strategy.ExecuteRestriction.EffectiveEndTime + now := time.Now() + start := now.Add(-1 * time.Second) + end := now.Add(5 * time.Minute) var tokenAddress string if strategy.GetPayType() == global_const.PayTypeERC20 { tokenAddress = config.GetTokenAddress(strategy.GetNewWork(), strategy.Erc20TokenType) @@ -35,8 +37,8 @@ func NewPaymasterDataInput(strategy *model.Strategy) *PaymasterDataInput { return &PaymasterDataInput{ Paymaster: *strategy.GetPaymasterAddress(), - ValidUntil: big.NewInt(end.Int64()), - ValidAfter: big.NewInt(start.Int64()), + ValidUntil: big.NewInt(end.Unix()), + ValidAfter: big.NewInt(start.Unix()), ERC20Token: common.HexToAddress(tokenAddress), ExchangeRate: big.NewInt(0), PayType: strategy.GetPayType(), diff --git a/common/paymaster_pay_type/paymaster_data_generate.go b/common/paymaster_pay_type/paymaster_data_generate.go index ebc08ebc..85e72ce6 100644 --- a/common/paymaster_pay_type/paymaster_data_generate.go +++ b/common/paymaster_pay_type/paymaster_data_generate.go @@ -40,6 +40,7 @@ var basicPaymasterDataFunc = func(data *paymaster_data.PaymasterDataInput, signa func init() { paymasterDataFuncMap[global_const.PayTypeProjectSponsor] = basicPaymasterDataFunc paymasterDataFuncMap[global_const.PayTypeERC20] = basicPaymasterDataFunc + paymasterDataFuncMap[global_const.PayTypeUserSponsor] = basicPaymasterDataFunc paymasterDataFuncMap[global_const.PayTypeSuperVerifying] = func(data *paymaster_data.PaymasterDataInput, signature []byte) ([]byte, error) { packed, err := BasicPaymasterDataAbiV06.Pack(data.ValidUntil, data.ValidAfter, data.ERC20Token, data.ExchangeRate) if err != nil { diff --git a/common/price_compoent/price_util.go b/common/price_compoent/price_util.go index 42a7a52f..287588e5 100644 --- a/common/price_compoent/price_util.go +++ b/common/price_compoent/price_util.go @@ -4,6 +4,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/config" "fmt" + "github.com/sirupsen/logrus" "golang.org/x/xerrors" "io" "io/ioutil" @@ -56,12 +57,22 @@ func GetPriceUsd(tokenType global_const.TokenType) (float64, error) { req.Header.Add("x-cg-demo-api-key", config.GetPriceOracleApiKey()) res, _ := http.DefaultClient.Do(req) + logrus.Debugf("get price req: %v", req) + logrus.Debugf("get price response: %v", res) + if res == nil { + return 0, xerrors.Errorf("get price error: %w", "response is nil") + } + if res.StatusCode != 200 { + return 0, xerrors.Errorf("get price error: %w", res.Status) + + } - defer res.Body.Close() body, _ := io.ReadAll(res.Body) bodystr := string(body) strarr := strings.Split(bodystr, ":") usdstr := strings.TrimRight(strarr[2], "}}") + defer res.Body.Close() + return strconv.ParseFloat(usdstr, 64) } diff --git a/common/utils/util.go b/common/utils/util.go index 1a202652..58418eee 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -59,7 +59,7 @@ func GenerateMockUservOperation() *map[string]any { "maxPriorityFeePerGas": "0x59682f00", "nonce": "0x00", "preVerificationGas": "0xae64", - "sender": "0xffdb071c2b58ccc10ad386f9bb4e8d3d664ce73c", + "sender": "0xFfDB071C2b58CCC10Ad386f9Bb4E8d3d664CE73c", "signature": "0xaa846693598194980f3bf50486be854704534c1622d0c2ee895a5a1ebe1508221909a27cc7971d9f522c8df13b9d8a6ee446d09ea7635f31c59d77d35d1281421c", "verificationGasLimit": "0x05fa35", } diff --git a/config/basic_config.json b/config/basic_config.json index 061fa5cc..6e680313 100644 --- a/config/basic_config.json +++ b/config/basic_config.json @@ -3,9 +3,6 @@ "ethereum-sepolia": { "chain_id": "11155111", "is_test": true, - "rpc_url": "https://eth-sepolia.g.alchemy.com/v2", - "api_key": "wKeLycGxgYRykgf0aGfcpEkUtqyLQg4v", - "signer_key" : "752d81d71afd0b25a09f24718baf82c0846cc3b68122cfb3a1d41529c8a46b05", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "v06_paymaster_address" : "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", @@ -19,9 +16,6 @@ "optimism-sepolia": { "chain_id": "11155420", "is_test": true, - "rpc_url": "https://opt-sepolia.g.alchemy.com/v2", - "api_key": "_z0GaU6Zk8RfIR1guuli8nqMdb8RPdp0", - "signer_key" : "1d8a58126e87e53edc7b24d58d1328230641de8c4242c135492bf5560e0ff421", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "v06_paymaster_address" : "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", @@ -35,9 +29,6 @@ "arbitrum-sepolia": { "chain_id": "421614", "is_test": true, - "rpc_url": "https://arb-sepolia.g.alchemy.com/v2", - "api_key": "xSBkiidslrZmlcWUOSF3AluKx0A9g_kl", - "signer_key" : "752d81d71afd0b25a09f24718baf82c0846cc3b68122cfb3a1d41529c8a46b05", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", "v06_paymaster_address" : "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", @@ -51,9 +42,6 @@ "scroll-sepolia": { "chain_id": "534351", "is_test": true, - "rpc_url": "https://sepolia-rpc.scroll.io", - "api_key": "9DGRNUARDVGDPZWN2G55I3Y5NG7HQJBUTH", - "signer_key" : "752d81d71afd0b25a09f24718baf82c0846cc3b68122cfb3a1d41529c8a46b05", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "v06_paymaster_address" : "0x0Fa9ee28202F8602E9a4C99Af799C75C29AFbC89", @@ -67,9 +55,6 @@ "starknet-sepolia": { "chain_id": "534351", "is_test": true, - "rpc_url": "https://starknet-sepolia.infura.io/v3", - "api_key": "0284f5a9fc55476698079b24e2f97909", - "signer_key" : "752d81d71afd0b25a09f24718baf82c0846cc3b68122cfb3a1d41529c8a46b05", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "v06_paymaster_address" : "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", @@ -83,9 +68,6 @@ "base-sepolia": { "chain_id": "84532", "is_test": true, - "rpc_url": "https://base-sepolia.g.alchemy.com/v2", - "api_key": "zUhtd18b2ZOTIJME6rv2Uwz9q7PBnnsa", - "signer_key" : "752d81d71afd0b25a09f24718baf82c0846cc3b68122cfb3a1d41529c8a46b05", "v06_entrypoint_address" : "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", "v07_entrypoint_address" : "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "v06_paymaster_address" : "0xa86cFf572E299B2704FBBCF77dcbbc7FEfFbcA06", @@ -121,8 +103,7 @@ }, "support_paymaster": { "ethereum-sepolia": [ - "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", - "0x3Da96267B98a33267249734FD8FFeC75093D3085" + "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f" ], "optimism-sepolia": [ "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", @@ -140,6 +121,5 @@ "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", "0x2" ] - }, - "price_oracle_api_key": "CG-ioE6p8cmmSFBFwJnKECCbZ7U" + } } diff --git a/config/secret_config.go b/config/secret_config.go index 89982f21..a50f1dd4 100644 --- a/config/secret_config.go +++ b/config/secret_config.go @@ -6,7 +6,10 @@ import ( "context" "encoding/json" "fmt" + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" + "github.com/sirupsen/logrus" "math/big" "os" "sync" @@ -16,8 +19,8 @@ var dsnTemplate = "host=%s port=%v user=%s password=%s dbname=%s TimeZone=%s ssl var secretConfig *model.SecretConfig var signerConfig = make(SignerConfigMap) -var depositer *global_const.EOA - +var withdrawer *global_const.EOA +var depositerAddress common.Address var sponsorTestNetClient *ethclient.Client var sponsorTestNetClientChainId *big.Int var sponsorMainNetClient *ethclient.Client @@ -38,10 +41,15 @@ func GetPaymasterSponsorChainId(isTestNet bool) *big.Int { return sponsorMainNetClientChainId } +var sponsorWhitelist = mapset.NewSet[string]() + type SignerConfigMap map[global_const.Network]*global_const.EOA -func GetDepositer() *global_const.EOA { - return depositer +func GetWithdrawerEoa() *global_const.EOA { + return withdrawer +} +func GetDepositerAddress() common.Address { + return depositerAddress } func secretConfigInit(secretConfigPath string) { if secretConfigPath == "" { @@ -67,7 +75,8 @@ func secretConfigInit(secretConfigPath string) { signerConfig[global_const.Network(network)] = eoa } - depositer, err = global_const.NewEoa(secretConfig.SponsorConfig.SponsorDepositPrivateKey) + depositerAddress = common.HexToAddress(secretConfig.SponsorConfig.SponsorDepositAddress) + withdrawer, err = global_const.NewEoa(secretConfig.SponsorConfig.SponsorWithdrawPrivateKey) if err != nil { panic(fmt.Sprintf("signer key error: %s", err)) } @@ -94,12 +103,14 @@ func secretConfigInit(secretConfigPath string) { sponsorTestNetClient = paymasterSponsorTestNetClient sponsorTestNetClientChainId = paymasterInnerClientChainId }) + logrus.Debugf("secretConfig [%v]", secretConfig) + if secretConfig.SponsorConfig.FreeSponsorWhitelist != nil { + sponsorWhitelist.Append(secretConfig.SponsorConfig.FreeSponsorWhitelist...) + } } -func IsSponsorWhitelist(address string) bool { - - //TODO - return true +func IsSponsorWhitelist(senderAddress string) bool { + return sponsorWhitelist.Contains(senderAddress) } func GetNetworkSecretConfig(network global_const.Network) model.NetWorkSecretConfig { return secretConfig.NetWorkSecretConfigMap[string(network)] diff --git a/gas_executor/gas_computor_test.go b/gas_executor/gas_computor_test.go index 1fd6f008..0d0c61cf 100644 --- a/gas_executor/gas_computor_test.go +++ b/gas_executor/gas_computor_test.go @@ -30,7 +30,13 @@ func testGetGasPrice(t *testing.T, chain global_const.Network) { t.Error(err) return } - t.Logf("gasprice:%v", gasprice) + jsonStr, err := json.Marshal(gasprice) + if err != nil { + t.Error(err) + return + + } + t.Logf("gasprice:%v", string(jsonStr)) } func TestComputeGas(t *testing.T) { diff --git a/gas_executor/gas_validate.go b/gas_executor/gas_validate.go index c8790d45..990c9c06 100644 --- a/gas_executor/gas_validate.go +++ b/gas_executor/gas_validate.go @@ -51,6 +51,7 @@ var ( func init() { gasValidateFuncMap[global_const.PayTypeProjectSponsor] = verifyingGasValidateFunc + gasValidateFuncMap[global_const.PayTypeUserSponsor] = verifyingGasValidateFunc gasValidateFuncMap[global_const.PayTypeERC20] = erc20GasValidateFunc gasValidateFuncMap[global_const.PayTypeSuperVerifying] = superGasValidateFunc } diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index 3a46e24f..94b046cf 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -37,15 +37,7 @@ func Paymaster(ctx *gin.Context) { jsonRpcRequest := model.JsonRpcRequest{} response := model.GetResponse() - // - //defer func() { - // if r := recover(); r != nil { - // errInfo := fmt.Sprintf("[panic]: err : [%v] , stack :[%v]", r, utils.GetCurrentGoroutineStack()) - // logrus.Error(errInfo) - // response.SetHttpCode(http.StatusInternalServerError).FailCode(ctx, http.StatusInternalServerError, fmt.Sprintf("%v", r)) - // } - // - //}() + network := ctx.Param("network") logrus.Debugf("Paymaster network: %s", network) if network == "" { @@ -188,6 +180,5 @@ func validateUserOpRequest(request *model.UserOpRequest) error { if request.Network == "" { return xerrors.Errorf("ForceNetwork is empty") } - return nil } diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go index 01857af9..a217bee2 100644 --- a/rpc_server/api/v1/sponsor.go +++ b/rpc_server/api/v1/sponsor.go @@ -43,17 +43,20 @@ func DepositSponsor(ctx *gin.Context) { response := model.GetResponse() if err := ctx.ShouldBindJSON(&request); err != nil { errStr := fmt.Sprintf("Request Error [%v]", err) + logrus.Errorf("Request Error [%v]", err) response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) return } if request.DepositSource != "dashboard" { errStr := fmt.Sprintf("not Support Source") + logrus.Errorf("Deposit Source Error :Not Support Source") response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) return } //validate Signature inputJson, err := json.Marshal(request) if err != nil { + logrus.Errorf("Marshal Error [%v]", err) response.SetHttpCode(http.StatusInternalServerError).FailCode(ctx, http.StatusInternalServerError, err.Error()) return } @@ -62,17 +65,20 @@ func DepositSponsor(ctx *gin.Context) { if request.DepositSource == "dashboard" { signerAddress = config.GetSponsorConfig().DashBoardSignerAddress } else { + logrus.Errorf("Deposit Source Error :Not Support Source") response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, "Deposit Source Error :Not Support Source") return } err = ValidateSignature(ctx.GetHeader("relay_hash"), ctx.GetHeader("relay_signature"), inputJson, signerAddress) if err != nil { + logrus.Errorf("Validate Signature Error [%v]", err) response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, err.Error()) return } //validate Deposit sender, amount, err := validateDeposit(&request) if err != nil { + logrus.Errorf("Validate Deposit Error [%v]", err) response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, err.Error()) return } @@ -87,6 +93,7 @@ func DepositSponsor(ctx *gin.Context) { } result, err := sponsor_manager.DepositSponsor(&depositInput) if err != nil { + logrus.Errorf("Deposit Sponsor Error [%v]", err) response.SetHttpCode(http.StatusInternalServerError).FailCode(ctx, http.StatusInternalServerError, err.Error()) return } @@ -151,7 +158,7 @@ func validateDeposit(request *model.DepositSponsorRequest) (sender *common.Addre if tx.To() == nil { return nil, nil, xerrors.Errorf("Tx To Address is nil") } - if tx.To().Hex() != config.GetDepositer().Address.String() { + if tx.To().Hex() != config.GetDepositerAddress().String() { return nil, nil, xerrors.Errorf("Tx To Address is not Sponsor Address") } value := tx.Value() @@ -253,7 +260,7 @@ func WithdrawSponsor(ctx *gin.Context) { toAddress := common.HexToAddress(request.RefundAddress) chainId := config.GetPaymasterSponsorChainId(request.IsTestNet) // Execute transfer - tx, err := utils.TransEth(config.GetDepositer().PrivateKey, &toAddress, client, ethWeiValue, chainId) + tx, err := utils.TransEth(config.GetWithdrawerEoa().PrivateKey, &toAddress, client, ethWeiValue, chainId) // WithDrawSponsor result, err := sponsor_manager.WithDrawSponsor(&request, tx.Hash().Hex()) if err != nil { diff --git a/rpc_server/api/v1/sponsor_test.go b/rpc_server/api/v1/sponsor_test.go index 272bbc73..82cd8077 100644 --- a/rpc_server/api/v1/sponsor_test.go +++ b/rpc_server/api/v1/sponsor_test.go @@ -10,7 +10,10 @@ import ( "encoding/json" "fmt" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/sirupsen/logrus" + "os" "testing" ) @@ -18,14 +21,15 @@ func TestValidateDeposit(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } + logrus.SetLevel(logrus.DebugLevel) + os.Setenv(model.EnvKey, model.UnitEnv) config.InitConfig("../../../config/basic_strategy_config.json", "../../../config/basic_config.json", "../../../config/secret_config.json") sponsor_manager.Init() request := &model.DepositSponsorRequest{ - DepositAddress: "0xFD44DF0Fe211d5EFDBe1423483Fcb3FDeF84540f", - TxHash: "0x367428ad744c2fd80054283f7143b934d630433f9c40a411d91e65893dbabdf1", - PayUserId: "5", - DepositSource: "dashboard", - IsTestNet: true, + TxHash: "0x9a4621f1f43be25b8c25480ea5fb86efe657161b67ef03474e16133ae63e0687", + PayUserId: "5", + DepositSource: "dashboard", + IsTestNet: true, } sender, amount, err := validateDeposit(request) if err != nil { @@ -41,11 +45,10 @@ func TestValidateSignature(t *testing.T) { //publicKey: 0401e57b7947d19b224a98700dea8bcff3dd556980823aca6182e12eebe64e42ecee690d4c2d6eee6bbf9f82423e38314beec2be0a6833741a917a8abaebf66a76 //address: 0x3aCF4b1F443a088186Cbd66c5F81479C6e968eCA request := &model.DepositSponsorRequest{ - DepositAddress: "0xFD44DF0Fe211d5EFDBe1423483Fcb3FDeF84540f", - TxHash: "0x367428ad744c2fd80054283f7143b934d630433f9c40a411d91e65893dbabdf1", - PayUserId: "5", - DepositSource: "dashboard", - IsTestNet: true, + TxHash: "0x367428ad744c2fd80054283f7143b934d630433f9c40a411d91e65893dbabdf1", + PayUserId: "5", + DepositSource: "dashboard", + IsTestNet: true, } jsonData, err := json.Marshal(request) @@ -78,3 +81,11 @@ func TestValidateSignature(t *testing.T) { } t.Logf("ValidateSignature success") } +func TestDemo(t *testing.T) { + t.Logf("Demo") + address := "0xFfDB071C2b58CCC10Ad386f9Bb4E8d3d664CE73c" + commonAddres := common.HexToAddress(address) + commonAddres.Hex() + t.Logf("commonAddres: %v", commonAddres.Hex()) + +} diff --git a/schedulor/user_op_event_listener.go b/schedulor/user_op_event_listener.go index 23f86620..1c4872dd 100644 --- a/schedulor/user_op_event_listener.go +++ b/schedulor/user_op_event_listener.go @@ -190,14 +190,14 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera logrus.Debugf("Not Support Network %v", network) return } - //if !paymasterAddressSet.Contains(event.Paymaster) { - // logrus.Debugf("UserOpEventComunicate: paymaster not support, %v", event.Paymaster) - // return - //} + if !paymasterAddressSet.Contains(event.Paymaster.String()) { + logrus.Debugf("UserOpEventComunicate: paymaster Address not support, %v", event.Paymaster) + return + } if !event.Success { _, err := sponsor_manager.ReleaseUserOpHashLockWhenFail(event.UserOpHash[:], true) if err != nil { - logrus.Errorf("ReleaseUserOpHashLockWhenFail failed: %v", err) + logrus.Errorf("ReleaseUserOpHashLockWhenFail paymaster:[%s] userOphash:[%s] Sender:[%s] reason: [%v]", event.Paymaster, event.UserOpHash, event.Sender, err) } return } @@ -214,7 +214,7 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera _, err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender.String(), event.UserOpHash[:], gasCostUsd, true) if err != nil { //TODO if is NetWorkError, need retry - logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) + logrus.Errorf("ReleaseBalanceWithActualCost paymaster:[%s] userOphash:[%s] Sender:[%s] reason: [%v]", event.Paymaster, event.UserOpHash, event.Sender, err) return } } diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 2da6b72d..6b3fcbda 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -160,10 +160,10 @@ type StrategyExecuteRestrictionJson struct { ChainIdWhiteList []string `json:"chain_id_whitelist"` } -// GetSuitableStrategy get suitable strategy by entryPointVersion, chain, +// GetSuitableStrategyWithOutCode get suitable strategy by entryPointVersion, chain, // // For Offical StrategyConfig, -func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain global_const.Network, gasUseToken global_const.TokenType) (*model.Strategy, error) { +func GetSuitableStrategyWithOutCode(entryPointVersion global_const.EntrypointVersion, chain global_const.Network, gasUseToken global_const.TokenType) (*model.Strategy, error) { if entryPointVersion == "" { entryPointVersion = global_const.EntrypointV06 } @@ -193,6 +193,9 @@ func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain PayType: payType, IsProjectErc20PayEnable: isPerc20Enable, }, + ExecuteRestriction: &model.StrategyExecuteRestriction{ + Status: global_const.StrategyStatusAchive, + }, Erc20TokenType: gasUseToken, } return strategy, nil diff --git a/service/dashboard_service/dashboard_service_test.go b/service/dashboard_service/dashboard_service_test.go index 0e47bfd6..15058fc0 100644 --- a/service/dashboard_service/dashboard_service_test.go +++ b/service/dashboard_service/dashboard_service_test.go @@ -36,7 +36,7 @@ func TestDashBoardService(t *testing.T) { } } func testGetSuitableStrategy(t *testing.T) { - strategy, err := GetSuitableStrategy("", global_const.EthereumSepolia, global_const.TokenTypeOP) + strategy, err := GetSuitableStrategyWithOutCode("", global_const.EthereumSepolia, global_const.TokenTypeOP) if err != nil { t.Error(err) } diff --git a/service/operator/operator_test.go b/service/operator/operator_test.go index 521fa033..f71d2d0c 100644 --- a/service/operator/operator_test.go +++ b/service/operator/operator_test.go @@ -7,9 +7,13 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/user_op" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/envirment" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" "encoding/json" "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" "github.com/sirupsen/logrus" "os" "testing" @@ -22,8 +26,12 @@ func TestOperator(t *testing.T) { config.InitConfig("../../config/basic_strategy_config.json", "../../config/basic_config.json", "../../config/secret_config.json") logrus.SetLevel(logrus.DebugLevel) immutableRequest := getMockTryPayUserOpRequest() + os.Setenv("Env", "unit") mockRequestNotSupport1559 := getMockTryPayUserOpRequest() mockRequestNotSupport1559.UserOp["maxPriorityFeePerGas"] = mockRequestNotSupport1559.UserOp["maxFeePerGas"] + sponsor_manager.Init() + dashboard_service.Init() + envirment.Environment.SetUnitEnv() tests := []struct { name string test func(t *testing.T) @@ -123,12 +131,21 @@ func TestOperator(t *testing.T) { testTryPayUserOpExecute(t, mockRequest) }, }, + { + "Test_NoSpectCode_TryPayUserOpExecute", + func(t *testing.T) { + request := model.UserOpRequest{ + StrategyCode: "8bced19b-505e-4d11-ae80-abbee3d3a38c", + Network: global_const.EthereumSepolia, + UserOp: *utils.GenerateMockUservOperation(), + UserPayErc20Token: global_const.TokenTypeUSDT, + } + testTryPayUserOpExecute(t, &request) + }, + }, } for _, tt := range tests { - if os.Getenv("GITHUB_ACTIONS") != "" && global_const.GitHubActionWhiteListSet.Contains(tt.name) { - t.Logf("Skip test [%s] in GitHub Actions", tt.name) - continue - } + t.Run(tt.name, tt.test) } @@ -160,7 +177,9 @@ func testGetSupportEntrypointExecute(t *testing.T) { t.Log(res) } func testTryPayUserOpExecute(t *testing.T, request *model.UserOpRequest) { - result, err := TryPayUserOpExecute(&model.ApiKeyModel{}, request) + result, err := TryPayUserOpExecute(&model.ApiKeyModel{ + UserId: 5, + }, request) if err != nil { t.Fatal(err) return @@ -209,7 +228,22 @@ func testTryPayUserOpExecute(t *testing.T, request *model.UserOpRequest) { func getMockTryPayUserOpRequest() *model.UserOpRequest { return &model.UserOpRequest{ - StrategyCode: "Ethereum_Sepolia_v06_verifyPaymaster", + StrategyCode: "123__GhhSA", + Network: global_const.EthereumSepolia, UserOp: *utils.GenerateMockUservOperation(), } } + +func TestWSclient(t *testing.T) { + os.Setenv("Env", "unit") + + t.Logf("Env: %v", os.Getenv("Env")) + //TODO + url := "wss://eth-sepolia.g.alchemy.com/v2/wKeLycGxgYRykgf0aGfcpEkUtqyLQg4v" + wsClient, err := ethclient.Dial(url) + if err != nil { + t.Error(err) + return + } + t.Log(wsClient) +} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 1b907362..18fc79e6 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -85,6 +85,9 @@ func estimateGas(userOp *user_op.UserOpInput, strategy *model.Strategy, paymaste func ValidateGas(userOp *user_op.UserOpInput, gasComputeResponse *model.ComputeGasResponse, strategy *model.Strategy) error { validateFunc := gas_executor.GetGasValidateFunc(strategy.GetPayType()) + if validateFunc == nil { + return xerrors.Errorf("ValidateGas Not Support PayType [%s]", strategy.GetPayType()) + } err := validateFunc(userOp, gasComputeResponse, strategy) if err != nil { return err @@ -212,7 +215,7 @@ func StrategyGenerate(request *model.UserOpRequest) (*model.Strategy, error) { strategyResult = strategy } else { - suitableStrategy, err := dashboard_service.GetSuitableStrategy(request.EntryPointVersion, request.Network, request.UserPayErc20Token) + suitableStrategy, err := dashboard_service.GetSuitableStrategyWithOutCode(request.EntryPointVersion, request.Network, request.UserPayErc20Token) if err != nil { return nil, err } diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 578b7457..db5c10ef 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -31,19 +31,19 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er } if strategy.ExecuteRestriction == nil { - return nil + return xerrors.Errorf("ExecuteRestriction is Empty") } - if strategy.ExecuteRestriction.Status != global_const.StrategyStatusAchieve { + if strategy.ExecuteRestriction.Status != global_const.StrategyStatusAchive { return xerrors.Errorf("strategy status is not active") } curTime := time.Now().Unix() //check Time if strategy.ExecuteRestriction.EffectiveStartTime != nil { - if curTime < strategy.ExecuteRestriction.EffectiveStartTime.Int64() { + if curTime < strategy.ExecuteRestriction.EffectiveStartTime.Int64() && strategy.ExecuteRestriction.EffectiveEndTime.Sign() > 0 { return xerrors.Errorf("curTime [%s] is OutOff EffectiveStartTime [%s]", curTime, strategy.ExecuteRestriction.EffectiveStartTime.Int64()) } } - if strategy.ExecuteRestriction.EffectiveEndTime != nil { + if strategy.ExecuteRestriction.EffectiveEndTime != nil && strategy.ExecuteRestriction.EffectiveEndTime.Sign() > 0 { if curTime > strategy.ExecuteRestriction.EffectiveEndTime.Int64() { return xerrors.Errorf("curTime [%s] is OutOff EffectiveEndTime [%s]", curTime, strategy.ExecuteRestriction.EffectiveEndTime.Int64()) } @@ -53,7 +53,7 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er return xerrors.Errorf("strategy not support erc20 token") } } - if strategy.ExecuteRestriction.GlobalMaxUSD != nil || strategy.ExecuteRestriction.GlobalMaxUSD.Sign() != 0 { + if strategy.ExecuteRestriction.GlobalMaxUSD != nil && strategy.ExecuteRestriction.GlobalMaxUSD.Sign() != 0 { curGlobalUse, err := GetStrategyGlobalUse(strategy) if err != nil { return err @@ -62,7 +62,7 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er return xerrors.Errorf("strategy global max usd use out of limit") } } - if strategy.ExecuteRestriction.DayMaxUSD != nil || strategy.ExecuteRestriction.DayMaxUSD.Sign() != 0 { + if strategy.ExecuteRestriction.DayMaxUSD != nil && strategy.ExecuteRestriction.DayMaxUSD.Sign() != 0 { curDayUse, err := GetStrategyDayUse(strategy) if err != nil { return err @@ -70,8 +70,14 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er if strategy.ExecuteRestriction.DayMaxUSD.Cmp(curDayUse) < 0 { return xerrors.Errorf("strategy day max usd use out of limit") } - } + if strategy.ExecuteRestriction.ChainIdWhiteList != nil && !strategy.ExecuteRestriction.ChainIdWhiteList.IsEmpty() { + netWorkStr := string(request.Network) + if !strategy.ExecuteRestriction.ChainIdWhiteList.Contains(netWorkStr) { + return xerrors.Errorf("strategy not support chainId [%s]", netWorkStr) + } + } + return nil }