diff --git a/common/model/api_key_info.go b/common/model/api_key_info.go index a18a33b..a22daf6 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/secret_config.go b/common/model/secret_config.go index 4e10c77..6bedde1 100644 --- a/common/model/secret_config.go +++ b/common/model/secret_config.go @@ -22,14 +22,12 @@ type SecretConfig struct { 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"` - FreeSponsorWhitelist []string `json:"free_sponsor_whitelist"` + 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 7e4145a..27f5f81 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/price_compoent/price_util.go b/common/price_compoent/price_util.go index c154d4f..a1177e6 100644 --- a/common/price_compoent/price_util.go +++ b/common/price_compoent/price_util.go @@ -57,6 +57,15 @@ 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 func(Body io.ReadCloser) { if Body == nil { diff --git a/config/basic_config.json b/config/basic_config.json index 010f898..6e68031 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", @@ -139,6 +121,5 @@ "0xF2147CA7f18e8014b76e1A98BaffC96ebB90a29f", "0x2" ] - }, - "price_oracle_api_key": "CG-ioE6p8cmmSFBFwJnKECCbZ7U" + } } diff --git a/config/secret_config.go b/config/secret_config.go index ecdde26..a50f1dd 100644 --- a/config/secret_config.go +++ b/config/secret_config.go @@ -7,6 +7,7 @@ import ( "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" @@ -18,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 @@ -44,8 +45,11 @@ 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 == "" { @@ -71,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)) } diff --git a/gas_executor/gas_computor_test.go b/gas_executor/gas_computor_test.go index 1fd6f00..0d0c61c 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/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index 0c99a5a..94b046c 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 == "" { diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go index 01857af..a217bee 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 0e98aad..82cd807 100644 --- a/rpc_server/api/v1/sponsor_test.go +++ b/rpc_server/api/v1/sponsor_test.go @@ -12,6 +12,8 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/sirupsen/logrus" + "os" "testing" ) @@ -19,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 { @@ -42,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) diff --git a/service/operator/operator_test.go b/service/operator/operator_test.go index 1c72479..f71d2d0 100644 --- a/service/operator/operator_test.go +++ b/service/operator/operator_test.go @@ -26,6 +26,7 @@ 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() @@ -227,7 +228,8 @@ 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(), } } diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index d33abd6..d5c5a3b 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -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 }