Commit 65c1774d authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

feat: gas price for deploy, deposit and withdraw (#1812)

parent 2e0c0396
......@@ -60,6 +60,7 @@ const (
optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable"
optionNameTransactionHash = "transaction"
optionNameSwapDeploymentGasPrice = "swap-deployment-gas-price"
optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address"
optionNameBlockTime = "block-time"
......@@ -234,6 +235,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().String(optionNamePostageContractAddress, "", "postage stamp contract address")
cmd.Flags().String(optionNameTransactionHash, "", "proof-of-identity transaction hash")
cmd.Flags().Uint64(optionNameBlockTime, 15, "chain block time")
cmd.Flags().String(optionNameSwapDeploymentGasPrice, "", "gas price in wei to use for deployment and funding")
}
func newLogger(cmd *cobra.Command, verbosity string) (logging.Logger, error) {
......
......@@ -33,6 +33,7 @@ func (c *command) initDeployCmd() error {
factoryAddress := c.config.GetString(optionNameSwapFactoryAddress)
swapInitialDeposit := c.config.GetString(optionNameSwapInitialDeposit)
swapEndpoint := c.config.GetString(optionNameSwapEndpoint)
deployGasPrice := c.config.GetString(optionNameSwapDeploymentGasPrice)
stateStore, err := node.InitStateStore(logger, dataDir)
if err != nil {
......@@ -91,6 +92,7 @@ func (c *command) initDeployCmd() error {
transactionService,
chequebookFactory,
swapInitialDeposit,
deployGasPrice,
)
return err
......
......@@ -153,6 +153,7 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
Transaction: c.config.GetString(optionNameTransactionHash),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
BlockTime: c.config.GetUint64(optionNameBlockTime),
DeployGasPrice: c.config.GetString(optionNameSwapDeploymentGasPrice),
})
if err != nil {
return err
......
......@@ -598,6 +598,7 @@ paths:
type: integer
required: true
description: amount of tokens to deposit
- $ref: "SwarmCommon.yaml#/components/parameters/GasPriceParameter"
tags:
- Chequebook
responses:
......@@ -624,6 +625,7 @@ paths:
type: integer
required: true
description: amount of tokens to withdraw
- $ref: "SwarmCommon.yaml#/components/parameters/GasPriceParameter"
tags:
- Chequebook
responses:
......
......@@ -74,6 +74,8 @@ password-file: /var/lib/bee/password
# swap-legacy-factory-addresses: ""
## initial deposit if deploying a new chequebook (default 10000000000000000)
# swap-initial-deposit: 10000000000000000
## gas price in wei to use for deployment and funding (default "")
# swap-deployment-gas-price: ""
## enable tracing
# tracing-enable: false
## endpoint to send tracing data (default "127.0.0.1:6831")
......
......@@ -81,6 +81,8 @@ BEE_CLEF_SIGNER_ENABLE=true
# BEE_SWAP_LEGACY_FACTORY_ADDRESSES=
## initial deposit if deploying a new chequebook (default 10000000000000000)
# BEE_SWAP_INITIAL_DEPOSIT=10000000000000000
## gas price in wei to use for deployment and funding (default "")
# BEE_SWAP_DEPLOYMENT_GAS_PRICE=
## enable tracing
# BEE_TRACING_ENABLE=false
## endpoint to send tracing data (default 127.0.0.1:6831)
......
......@@ -74,6 +74,8 @@ password-file: /usr/local/var/lib/swarm-bee/password
# swap-legacy-factory-addresses: ""
## initial deposit if deploying a new chequebook (default 10000000000000000)
# swap-initial-deposit: 10000000000000000
## gas price in wei to use for deployment and funding (default "")
# swap-deployment-gas-price: ""
## enable tracing
# tracing-enable: false
## endpoint to send tracing data (default "127.0.0.1:6831")
......
......@@ -64,6 +64,8 @@ password-file: ./password
# swap-legacy-factory-addresses: ""
## initial deposit if deploying a new chequebook (default 10000000000000000)
# swap-initial-deposit: 10000000000000000
## gas price in wei to use for deployment and funding (default "")
# swap-deployment-gas-price: ""
## enable tracing
# tracing-enable: false
## endpoint to send tracing data (default "127.0.0.1:6831")
......
......@@ -335,7 +335,18 @@ func (s *Service) chequebookWithdrawHandler(w http.ResponseWriter, r *http.Reque
return
}
txHash, err := s.chequebook.Withdraw(r.Context(), amount)
ctx := r.Context()
if price, ok := r.Header[gasPriceHeader]; ok {
p, ok := big.NewInt(0).SetString(price[0], 10)
if !ok {
s.logger.Error("debug api: withdraw: bad gas price")
jsonhttp.BadRequest(w, errBadGasPrice)
return
}
ctx = sctx.SetGasPrice(ctx, p)
}
txHash, err := s.chequebook.Withdraw(ctx, amount)
if errors.Is(err, chequebook.ErrInsufficientFunds) {
jsonhttp.BadRequest(w, errChequebookInsufficientFunds)
s.logger.Debugf("debug api: chequebook withdraw: %v", err)
......@@ -367,7 +378,18 @@ func (s *Service) chequebookDepositHandler(w http.ResponseWriter, r *http.Reques
return
}
txHash, err := s.chequebook.Deposit(r.Context(), amount)
ctx := r.Context()
if price, ok := r.Header[gasPriceHeader]; ok {
p, ok := big.NewInt(0).SetString(price[0], 10)
if !ok {
s.logger.Error("debug api: deposit: bad gas price")
jsonhttp.BadRequest(w, errBadGasPrice)
return
}
ctx = sctx.SetGasPrice(ctx, p)
}
txHash, err := s.chequebook.Deposit(ctx, amount)
if errors.Is(err, chequebook.ErrInsufficientFunds) {
jsonhttp.BadRequest(w, errChequebookInsufficientFunds)
s.logger.Debugf("debug api: chequebook deposit: %v", err)
......
......@@ -130,54 +130,115 @@ func TestChequebookWithdraw(t *testing.T) {
txHash := common.HexToHash("0xfffff")
chequebookWithdrawFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if amount.Cmp(big.NewInt(500)) == 0 {
return txHash, nil
t.Run("ok", func(t *testing.T) {
chequebookWithdrawFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if amount.Cmp(big.NewInt(500)) == 0 {
return txHash, nil
}
return common.Hash{}, nil
}
return common.Hash{}, nil
}
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookWithdrawFunc(chequebookWithdrawFunc)},
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookWithdrawFunc(chequebookWithdrawFunc)},
})
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/withdraw?amount=500", http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
})
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
t.Run("custom gas", func(t *testing.T) {
chequebookWithdrawFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if sctx.GetGasPrice(ctx).Cmp(big.NewInt(10)) != 0 {
return common.Hash{}, errors.New("wrong gas price")
}
if amount.Cmp(big.NewInt(500)) == 0 {
return txHash, nil
}
return common.Hash{}, nil
}
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookWithdrawFunc(chequebookWithdrawFunc)},
})
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/withdraw?amount=500", http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/withdraw?amount=500", http.StatusOK,
jsonhttptest.WithRequestHeader("Gas-Price", "10"),
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
})
}
func TestChequebookDeposit(t *testing.T) {
txHash := common.HexToHash("0xfffff")
chequebookDepositFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if amount.Cmp(big.NewInt(700)) == 0 {
return txHash, nil
t.Run("ok", func(t *testing.T) {
chequebookDepositFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if amount.Cmp(big.NewInt(700)) == 0 {
return txHash, nil
}
return common.Hash{}, nil
}
return common.Hash{}, nil
}
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookDepositFunc(chequebookDepositFunc)},
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookDepositFunc(chequebookDepositFunc)},
})
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/deposit?amount=700", http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
})
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
t.Run("custom gas", func(t *testing.T) {
chequebookDepositFunc := func(ctx context.Context, amount *big.Int) (hash common.Hash, err error) {
if sctx.GetGasPrice(ctx).Cmp(big.NewInt(10)) != 0 {
return common.Hash{}, errors.New("wrong gas price")
}
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/deposit?amount=700", http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if amount.Cmp(big.NewInt(700)) == 0 {
return txHash, nil
}
return common.Hash{}, nil
}
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
testServer := newTestServer(t, testServerOptions{
ChequebookOpts: []mock.Option{mock.WithChequebookDepositFunc(chequebookDepositFunc)},
})
expected := &debugapi.ChequebookTxResponse{TransactionHash: txHash}
var got *debugapi.ChequebookTxResponse
jsonhttptest.Request(t, testServer.Client, http.MethodPost, "/chequebook/deposit?amount=700", http.StatusOK,
jsonhttptest.WithRequestHeader("Gas-Price", "10"),
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got address: %+v, expected: %+v", got, expected)
}
})
}
func TestChequebookLastCheques(t *testing.T) {
......
......@@ -16,6 +16,7 @@ import (
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p/libp2p"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement"
"github.com/ethersphere/bee/pkg/settlement/swap"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
......@@ -139,6 +140,7 @@ func InitChequebookService(
transactionService transaction.Service,
chequebookFactory chequebook.Factory,
initialDeposit string,
deployGasPrice string,
) (chequebook.Service, error) {
chequeSigner := chequebook.NewChequeSigner(signer, chainID)
......@@ -147,6 +149,14 @@ func InitChequebookService(
return nil, fmt.Errorf("initial swap deposit \"%s\" cannot be parsed", initialDeposit)
}
if deployGasPrice != "" {
gasPrice, ok := new(big.Int).SetString(deployGasPrice, 10)
if !ok {
return nil, fmt.Errorf("deploy gas price \"%s\" cannot be parsed", deployGasPrice)
}
ctx = sctx.SetGasPrice(ctx, gasPrice)
}
chequebookService, err := chequebook.Init(
ctx,
chequebookFactory,
......
......@@ -137,6 +137,7 @@ type Options struct {
PostageContractAddress string
PriceOracleAddress string
BlockTime uint64
DeployGasPrice string
}
const (
......@@ -271,6 +272,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
transactionService,
chequebookFactory,
o.SwapInitialDeposit,
o.DeployGasPrice,
)
if err != nil {
return nil, err
......
......@@ -13,6 +13,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/erc20"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/bee/pkg/storage"
......@@ -324,7 +325,7 @@ func (s *service) Withdraw(ctx context.Context, amount *big.Int) (hash common.Ha
request := &transaction.TxRequest{
To: &s.address,
Data: callData,
GasPrice: nil,
GasPrice: sctx.GetGasPrice(ctx),
GasLimit: 0,
Value: big.NewInt(0),
}
......
......@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/go-sw3-abi/sw3abi"
"golang.org/x/net/context"
......@@ -80,7 +81,7 @@ func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHard
request := &transaction.TxRequest{
To: &c.address,
Data: callData,
GasPrice: nil,
GasPrice: sctx.GetGasPrice(ctx),
GasLimit: 0,
Value: big.NewInt(0),
}
......
......@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/sctx"
"github.com/ethersphere/bee/pkg/settlement/swap/transaction"
"github.com/ethersphere/go-sw3-abi/sw3abi"
)
......@@ -78,7 +79,7 @@ func (c *erc20Service) Transfer(ctx context.Context, address common.Address, val
request := &transaction.TxRequest{
To: &c.address,
Data: callData,
GasPrice: nil,
GasPrice: sctx.GetGasPrice(ctx),
GasLimit: 0,
Value: big.NewInt(0),
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment