Skip to content

Commit

Permalink
optimise gas price
Browse files Browse the repository at this point in the history
  • Loading branch information
lizhenchun committed Aug 13, 2021
1 parent 58a0832 commit 3ba5a00
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 51 deletions.
27 changes: 27 additions & 0 deletions eth/contract.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package eth

import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
"strings"
)

Expand All @@ -19,3 +23,26 @@ func DeployContract(opts *bind.TransactOpts, backend bind.ContractBackend, jsonA
}
return address, tx, nil
}

func EstimateContractMethodGas(param TransactBaseParam, backend bind.ContractBackend, contractAddress common.Address, input []byte) (int64, error) {
err := EnsureTransactGasPrice(backend, &param)
if err != nil {
return 0, err
}

ethValue := param.EthValue
if ethValue == nil {
ethValue = big.NewInt(0)
}
msg := ethereum.CallMsg{From: param.From, To: &contractAddress,
GasPrice: param.GasPrice,
GasFeeCap: param.GasFeeCap,
GasTipCap: param.GasTipCap,
Value: ethValue, Data: input}

gasLimit, err := backend.EstimateGas(context.Background(), msg)
if err != nil {
return 0, fmt.Errorf("failed to estimate gas needed: %v", err)
}
return int64(gasLimit), nil
}
27 changes: 3 additions & 24 deletions eth/erc20.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package eth

import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -118,39 +115,21 @@ func (this *Erc20Contract) EstimateTransferGas(param TransactBaseParam, to commo
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc20Contract) EstimateApproveGas(param TransactBaseParam, spender common.Address, tokens *big.Int) (int64, error) {
input, err := this.abi.Pack("approve", spender, tokens)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc20Contract) EstimateTransferFromGas(param TransactBaseParam, from common.Address, to common.Address, tokens *big.Int) (int64, error) {
input, err := this.abi.Pack("transferFrom", from, to, tokens)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
}

func (this *Erc20Contract) EstimateMethodGas(param TransactBaseParam, input []byte) (int64, error) {
ethValue := param.EthValue
if ethValue == nil {
ethValue = big.NewInt(0)
}
msg := ethereum.CallMsg{From: param.From, To: &this.contractAddress,
GasPrice: param.GasPrice,
GasFeeCap: param.GasFeeCap,
GasTipCap: param.GasTipCap,
Value: ethValue, Data: input}

gasLimit, err := this.backend.EstimateGas(context.Background(), msg)
if err != nil {
return 0, fmt.Errorf("failed to estimate gas needed: %v", err)
}
return int64(gasLimit), nil
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}
31 changes: 5 additions & 26 deletions eth/erc721.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package eth

import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -191,55 +188,37 @@ func (this *Erc721Contract) EstimateSafeTransferFromGas(param TransactBaseParam,
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc721Contract) EstimateSafeTransferFrom2Gas(param TransactBaseParam, from common.Address, to common.Address, tokenId *big.Int, data []byte) (int64, error) {
input, err := this.abi.Pack("safeTransferFrom", from, to, tokenId, data)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc721Contract) EstimateTransferFromGas(param TransactBaseParam, from common.Address, to common.Address, tokenId *big.Int) (int64, error) {
input, err := this.abi.Pack("transferFrom", from, to, tokenId)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc721Contract) EstimateApproveGas(param TransactBaseParam, to common.Address, tokenId *big.Int) (int64, error) {
input, err := this.abi.Pack("approve", to, tokenId)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}

func (this *Erc721Contract) EstimateSetApprovalForAllGas(param TransactBaseParam, operator common.Address, approved bool) (int64, error) {
input, err := this.abi.Pack("setApprovalForAll", operator, approved)
if err != nil {
return 0, err
}
return this.EstimateMethodGas(param, input)
}

func (this *Erc721Contract) EstimateMethodGas(param TransactBaseParam, input []byte) (int64, error) {
ethValue := param.EthValue
if ethValue == nil {
ethValue = big.NewInt(0)
}
msg := ethereum.CallMsg{From: param.From, To: &this.contractAddress,
GasPrice: param.GasPrice,
GasFeeCap: param.GasFeeCap,
GasTipCap: param.GasTipCap,
Value: ethValue, Data: input}

gasLimit, err := this.backend.EstimateGas(context.Background(), msg)
if err != nil {
return 0, fmt.Errorf("failed to estimate gas needed: %v", err)
}
return int64(gasLimit), nil
return EstimateContractMethodGas(param, this.backend, this.contractAddress, input)
}
51 changes: 50 additions & 1 deletion eth/transact.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eth

import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -11,10 +12,46 @@ import (

type TransactBaseParam struct {
From common.Address
EthValue *big.Int
GasPrice *big.Int
GasFeeCap *big.Int
GasTipCap *big.Int
EthValue *big.Int
}

func EnsureTransactGasPrice(backend bind.ContractBackend, param *TransactBaseParam) error {
head, err := backend.HeaderByNumber(context.Background(), nil)
if err != nil {
return err
}

if head.BaseFee == nil {
if param.GasPrice == nil {
price, err := backend.SuggestGasPrice(context.Background())
if err != nil {
return err
}
param.GasPrice = price
}
} else {
if param.GasTipCap == nil {
tip, err := backend.SuggestGasTipCap(context.Background())
if err != nil {
return err
}
param.GasTipCap = tip
}
if param.GasFeeCap == nil {
gasFeeCap := new(big.Int).Add(
param.GasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
)
param.GasFeeCap = gasFeeCap
}
if param.GasFeeCap.Cmp(param.GasTipCap) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", param.GasFeeCap, param.GasTipCap)
}
}
return nil
}

func MakeTransactOpts(w *wallet.EthWallet, param TransactBaseParam, gasLimit int64, nonce int64) (*bind.TransactOpts, error) {
Expand Down Expand Up @@ -60,6 +97,18 @@ func TransferEther(opts *bind.TransactOpts, backend bind.ContractBackend, addres
gasLimit = wallet.EtherTransferGas
}

param := TransactBaseParam{GasPrice: opts.GasPrice,
GasFeeCap: opts.GasFeeCap,
GasTipCap: opts.GasTipCap,
}
err := EnsureTransactGasPrice(backend, &param)
if err != nil {
return nil, err
}
opts.GasPrice = param.GasPrice
opts.GasFeeCap = param.GasFeeCap
opts.GasTipCap = param.GasTipCap

var tx *types.Transaction
var input []byte
if opts.GasFeeCap == nil {
Expand Down
Loading

0 comments on commit 3ba5a00

Please sign in to comment.