Skip to content

Commit

Permalink
Merge pull request #8 from KyberNetwork/fix/estimate-bundle-endpoint
Browse files Browse the repository at this point in the history
fix: estimate gas for bundle
  • Loading branch information
tiennampham23 authored Mar 15, 2024
2 parents 9c06e2d + 499c259 commit e7fbdde
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 54 deletions.
54 changes: 0 additions & 54 deletions eth/api_simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/gasestimator"
"github.com/ethereum/go-ethereum/internal/ethapi"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -506,56 +505,3 @@ func (b *SimulationAPIBackend) CallBundle(ctx context.Context, args CallBundleAr
ret["bundleHash"] = "0x" + common.Bytes2Hex(bundleHash.Sum(nil))
return ret, nil
}

func (b *SimulationAPIBackend) EstimateGasBundle(ctx context.Context, args EstimateGasBundleArgs, overrides *ethapi.StateOverride) ([]uint64, error) {
txs := args.Transactions

if b.stateDb == nil {
return nil, fmt.Errorf("statedb is empty")
}

if b.currentBlock == nil {
return nil, fmt.Errorf("current block is empty")
}

var (
stateDB = b.stateDb.Copy()
parent = b.currentBlock.Header()
chainConfig = b.eth.BlockChain().Config()
gasCap = b.eth.Config().RPCGasCap

opts = &gasestimator.Options{
Config: chainConfig,
Chain: b.eth.BlockChain(),
Header: parent,
State: stateDB,
IsNotCopyStateDB: true,
ErrorRatio: estimateGasErrorRatio,
}
)
if err := overrides.Apply(stateDB); err != nil {
log.Error("Failed to apply overrides to state db", "err", err)
return nil, err
}

var gasEstimatedBundles []uint64

for _, tx := range txs {
// Run the gas estimation andwrap any revertals into a custom return
call, err := tx.ToMessage(gasCap, parent.BaseFee)
if err != nil {
return nil, err
}
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
if err != nil {
if len(revert) > 0 {
return nil, newRevertError(revert)
}
return nil, err
}

gasEstimatedBundles = append(gasEstimatedBundles, estimate)
}

return gasEstimatedBundles, nil
}
47 changes: 47 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,45 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
return hexutil.Uint64(estimate), nil
}

func DoEstimateGasBundle(ctx context.Context, b Backend, bundle EstimateGasBundleArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) ([]hexutil.Uint64, error) {
// Retrieve the base state and mutate it with any overrides
stateDB, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if stateDB == nil || err != nil {
return nil, err
}
if err = overrides.Apply(stateDB); err != nil {
return nil, err
}
// Construct the gas estimator option from the user input
opts := &gasestimator.Options{
Config: b.ChainConfig(),
Chain: NewChainContext(ctx, b),
Header: header,
State: stateDB,
IsNotCopyStateDB: true,
ErrorRatio: estimateGasErrorRatio,
}

estimateGas := make([]hexutil.Uint64, 0, len(bundle.Transactions))
for _, args := range bundle.Transactions {
// Run the gas estimation andwrap any revertals into a custom return
call, err := args.ToMessage(gasCap, header.BaseFee)
if err != nil {
return nil, err
}
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
if err != nil {
if len(revert) > 0 {
return nil, newRevertError(revert)
}
return nil, err
}
estimateGas = append(estimateGas, hexutil.Uint64(estimate))
}
return estimateGas, nil

}

// EstimateGas returns the lowest possible gas limit that allows the transaction to run
// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It
// returns error if the transaction would revert or if there are unexpected failures. The returned
Expand All @@ -1210,6 +1249,14 @@ func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, b
return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap())
}

func (s *BlockChainAPI) EstimateGasBundle(ctx context.Context, args EstimateGasBundleArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) ([]hexutil.Uint64, error) {
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
return DoEstimateGasBundle(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap())
}

// RPCMarshalHeader converts the given header to the RPC output .
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
result := map[string]interface{}{
Expand Down
4 changes: 4 additions & 0 deletions internal/ethapi/transaction_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ type TransactionArgs struct {
blobSidecarAllowed bool
}

type EstimateGasBundleArgs struct {
Transactions []TransactionArgs `json:"transactions"`
}

// from retrieves the transaction sender address.
func (args *TransactionArgs) from() common.Address {
if args.From == nil {
Expand Down
5 changes: 5 additions & 0 deletions internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ web3._extend({
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter, null],
outputFormatter: web3._extend.utils.toDecimal
}),
new web3._extend.Method({
name: 'estimateGasBundle',
call: 'eth_estimateGasBundle',
params: 3,
}),
new web3._extend.Method({
name: 'submitTransaction',
call: 'eth_submitTransaction',
Expand Down

0 comments on commit e7fbdde

Please sign in to comment.