Skip to content

Commit

Permalink
Gas Tank
Browse files Browse the repository at this point in the history
  • Loading branch information
cherry-yl-sh committed May 21, 2024
1 parent 1d26e1b commit 7b1c01d
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 38 deletions.
2 changes: 1 addition & 1 deletion common/data_utils/data_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func GetUserOpWithPaymasterAndDataForSimulate(op user_op.UserOpInput, strategy *
op.CallGasLimit = global_const.DummyCallGasLimit
}

paymasterData, err := executor.GetPaymasterData(&op, strategy, paymasterDataInput)
paymasterData, _, err := executor.GetPaymasterData(&op, strategy, paymasterDataInput)
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions common/model/api_key_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package model
import "golang.org/x/time/rate"

type ApiKeyModel struct {
Disable bool `gorm:"column:disable;type:bool" json:"disable"`
ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"`
RateLimit rate.Limit `gorm:"column:rate_limit;type:int" json:"rate_limit"`
Disable bool `json:"disable"`
ApiKey string `json:"api_key"`
RateLimit rate.Limit `json:"rate_limit"`
UserId int64 `json:"user_id"`
}
1 change: 1 addition & 0 deletions common/model/secret_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ 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"`
}

type NetWorkSecretConfig struct {
Expand Down
3 changes: 2 additions & 1 deletion common/model/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ type Strategy struct {
EntryPointInfo *EntryPointInfo `json:"entrypoint_info"`
Description string `json:"description"`
ExecuteRestriction *StrategyExecuteRestriction `json:"execute_restriction"`
Erc20TokenType global_const.TokenType
Erc20TokenType global_const.TokenType `json:"-"`
ProjectSponsor bool `json:"-"`
}
type PaymasterInfo struct {
PayMasterAddress *common.Address `json:"paymaster_address"`
Expand Down
17 changes: 10 additions & 7 deletions common/network/ethereum_adaptable_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,18 +539,21 @@ func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, str
}

}
func (executor *EthereumExecutor) GetPaymasterData(userOp *user_op.UserOpInput, strategy *model.Strategy, paymasterDataInput *paymaster_data.PaymasterDataInput) ([]byte, error) {
userOpHash, _, err := executor.GetUserOpHash(userOp, strategy)
if err != nil {
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)
if hashErr != nil {
logrus.Errorf("GetUserOpHash error [%v]", err)
return nil, err
return nil, nil, err
}
signer := config.GetSigner(strategy.GetNewWork())
signature, err := utils.GetSign(userOpHash, signer.PrivateKey)
if err != nil {
return nil, err
return nil, nil, err
}
dataGenerateFunc := paymaster_pay_type.GetGenerateFunc(strategy.GetPayType())
paymasterData, err := dataGenerateFunc(paymasterDataInput, signature)
return paymasterData, err
paymasterData, generateDataErr := dataGenerateFunc(paymasterDataInput, signature)
if generateDataErr != nil {
return nil, nil, generateDataErr
}
return paymasterData, userOpHash, nil
}
4 changes: 2 additions & 2 deletions common/network/ethereum_adaptable_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func testGetPaymasterData(t *testing.T, chain global_const.Network, input *user_
dataInput := paymaster_data.NewPaymasterDataInput(strategy)
dataInput.PaymasterPostOpGasLimit = global_const.DummyPaymasterPostoperativelyBigint
dataInput.PaymasterVerificationGasLimit = global_const.DummyPaymasterOversimplificationBigint
paymasterData, err := executor.GetPaymasterData(input, strategy, dataInput)
paymasterData, _, err := executor.GetPaymasterData(input, strategy, dataInput)
if err != nil {
t.Error(err)
return
Expand All @@ -301,7 +301,7 @@ func testSimulateHandleOp(t *testing.T, chain global_const.Network, strategy *mo
dataInput := paymaster_data.NewPaymasterDataInput(strategy)
op.AccountGasLimits = user_op.DummyAccountGasLimits
op.GasFees = user_op.DummyGasFees
paymasterData, err := sepoliaExector.GetPaymasterData(op, strategy, dataInput)
paymasterData, _, err := sepoliaExector.GetPaymasterData(op, strategy, dataInput)
if err != nil {
t.Error(err)
return
Expand Down
10 changes: 10 additions & 0 deletions common/price_compoent/price_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"io/ioutil"
"log"
"math/big"
"net/http"
"net/url"
"os"
Expand All @@ -29,6 +30,15 @@ func init() {
URLMap[global_const.TokenTypeOP] = "https://api.coingecko.com/api/v3/simple/price?ids=optimism&vs_currencies=usd"
}

func GetTokenCostInUsd(tokenType global_const.TokenType, amount *big.Float) (*big.Float, error) {
price, err := GetPriceUsd(tokenType)
if err != nil {
return nil, xerrors.Errorf("get price error: %w", err)
}
amountInUsd := new(big.Float).Mul(new(big.Float).SetFloat64(price), amount)
return amountInUsd, nil
}

func GetPriceUsd(tokenType global_const.TokenType) (float64, error) {

if global_const.IsStableToken(tokenType) {
Expand Down
5 changes: 5 additions & 0 deletions config/secret_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ func secretConfigInit(secretConfigPath string) {
signerConfig[global_const.Network(network)] = eoa
}
}
func IsSponsorWhitelist(address string) bool {

//TODO
return true
}
func GetNetworkSecretConfig(network global_const.Network) model.NetWorkSecretConfig {
return secretConfig.NetWorkSecretConfigMap[string(network)]
}
Expand Down
4 changes: 3 additions & 1 deletion rpc_server/api/v1/paymaster.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ func TryPayUserOperationMethod() MethodFunctionFunc {
}
logrus.Debugf("After Validate ")

if result, err := operator.TryPayUserOpExecute(request); err != nil {
apiKeyModel := ctx.MustGet(global_const.ContextKeyApiMoDel)

if result, err := operator.TryPayUserOpExecute(apiKeyModel.(*model.ApiKeyModel), request); err != nil {
return nil, xerrors.Errorf("TryPayUserOpExecute ERROR [%v]", err)
} else {
return result, nil
Expand Down
6 changes: 2 additions & 4 deletions rpc_server/middlewares/rate_limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ var limiter map[string]*rate.Limiter
func RateLimiterByApiKeyHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
if exists, current := utils.CurrentUser(ctx); exists {
apiKeyModel, _ := ctx.Get(global_const.ContextKeyApiMoDel)
apiKeyModel := ctx.MustGet(global_const.ContextKeyApiMoDel)
defaultLimit := DefaultLimit
if apiKeyModel != nil {
defaultLimit = apiKeyModel.(*model.ApiKeyModel).RateLimit
}
defaultLimit = apiKeyModel.(*model.ApiKeyModel).RateLimit
if limiting(&current, defaultLimit) {
ctx.Next()
} else {
Expand Down
98 changes: 98 additions & 0 deletions schedulor/UserOpEventListener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package schedulor

import (
"AAStarCommunity/EthPaymaster_BackService/common/global_const"
"AAStarCommunity/EthPaymaster_BackService/common/price_compoent"
"AAStarCommunity/EthPaymaster_BackService/config"
"AAStarCommunity/EthPaymaster_BackService/sponsor_manager"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/sirupsen/logrus"
"math/big"
)

func AddListener(client ethclient.Client, network global_const.Network) {
entryPointAddress, _ := config.GetSupportEntryPoints(network)
if entryPointAddress == nil {
logrus.Debugf("Not Support Network %v", network)
return
}
for _, address := range entryPointAddress.ToSlice() {
contractAddress := common.HexToAddress(address)
query := ethereum.FilterQuery{
Addresses: []common.Address{contractAddress},
}
sub, err := client.SubscribeFilterLogs(nil, query, nil)
if err != nil {
logrus.Errorf("SubscribeFilterLogs failed: %v", err)
return
}
logs := make(chan types.Log)
go func() {
for {
select {
case err := <-sub.Err():
logrus.Errorf("SubscribeFilterLogs failed: %v", err)
return
case vLog := <-logs:
if vLog.Removed {
continue
}
//TODO
//UserOpEventComunicate(network, ContractUserOperationEvent{})
}
}
}()
//TODO
//client.SubscribeFilterLogs()
}
//TODO
}

type ContractUserOperationEvent struct {
UserOpHash [32]byte
Sender string
Paymaster string
Nonce *big.Int
Success bool
ActualGasCost *big.Int
ActualGasUsed *big.Int
Raw types.Log
}

func UserOpEventComunicate(network global_const.Network, event ContractUserOperationEvent) {
paymasterAddressSet, _ := config.GetSupportPaymaster(network)
if paymasterAddressSet == nil {
logrus.Debugf("Not Support Network %v", network)
return
}
if !paymasterAddressSet.Contains(event.Paymaster) {
logrus.Debugf("UserOpEventComunicate: paymaster not support, %v", event.Paymaster)
return
}
if !event.Success {
err := sponsor_manager.ReleaseUserOpHashLock(event.UserOpHash[:])
if err != nil {
logrus.Errorf("ReleaseUserOpHashLock failed: %v", err)
}
return
}
gasCostEther := new(big.Float).SetInt(event.ActualGasCost)
gasCostEther = new(big.Float).Quo(gasCostEther, new(big.Float).SetInt64(1e18))
//logrus.Infof("UserOpEventComunicate: %v, %v, %v, %v", event.UserOpHash, event.Sender, event.ActualGasCost, gasCostEther)
gasCostUsd, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, gasCostEther)
if err != nil {
//TODO if is NetWorkError, need retry
logrus.Errorf("GetTokenCostInUsd failed: %v", err)
return
}

err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], network, gasCostUsd)
if err != nil {
//TODO if is NetWorkError, need retry
logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err)
return
}
}
3 changes: 3 additions & 0 deletions service/dashboard_service/dashboard_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func GetStrategyByCode(strategyCode string, entryPointVersion global_const.Entry
if err != nil {
return nil, err
}
strategy.ProjectSponsor = true

return strategy, nil
}
Expand Down Expand Up @@ -223,6 +224,7 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool {
}

type ApiKeyDbModel struct {
UserId int64 `gorm:"column:user_id;type:integer" json:"user_id"`
Disable bool `gorm:"column:disable;type:bool" json:"disable"`
ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"`
KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"`
Expand All @@ -242,6 +244,7 @@ func convertApiKeyDbModelToApiKeyModel(apiKeyDbModel *ApiKeyDbModel) *model.ApiK
Disable: apiKeyDbModel.Disable,
ApiKey: apiKeyDbModel.ApiKey,
RateLimit: 10,
UserId: apiKeyDbModel.UserId,
}
}
func GetAPiInfoByApiKey(apiKey string) (*model.ApiKeyModel, error) {
Expand Down
2 changes: 1 addition & 1 deletion service/operator/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func testGetSupportEntrypointExecute(t *testing.T) {
t.Log(res)
}
func testTryPayUserOpExecute(t *testing.T, request *model.UserOpRequest) {
result, err := TryPayUserOpExecute(request)
result, err := TryPayUserOpExecute(&model.ApiKeyModel{}, request)
if err != nil {
t.Fatal(err)
return
Expand Down
Loading

0 comments on commit 7b1c01d

Please sign in to comment.