Skip to content

Commit

Permalink
[api] refactor call param parsing (#4479)
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc authored Nov 29, 2024
1 parent 5b64c2b commit 9922923
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 46 deletions.
28 changes: 13 additions & 15 deletions api/web3server.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,11 @@ func (svr *web3Handler) getTransactionCount(in *gjson.Result) (interface{}, erro
}

func (svr *web3Handler) call(in *gjson.Result) (interface{}, error) {
callerAddr, to, gasLimit, _, value, data, err := parseCallObject(in)
callMsg, err := parseCallObject(in)
if err != nil {
return nil, err
}
callerAddr, to, gasLimit, value, data := callMsg.From, callMsg.To, callMsg.Gas, callMsg.Value, callMsg.Data
if to == _metamaskBalanceContractAddr {
return nil, nil
}
Expand Down Expand Up @@ -435,11 +436,11 @@ func (svr *web3Handler) call(in *gjson.Result) (interface{}, error) {
}

func (svr *web3Handler) estimateGas(in *gjson.Result) (interface{}, error) {
from, to, gasLimit, _, value, data, err := parseCallObject(in)
callMsg, err := parseCallObject(in)
if err != nil {
return nil, err
}

from, to := callMsg.From, callMsg.To
var (
tx *types.Transaction
toAddr *common.Address
Expand All @@ -453,11 +454,11 @@ func (svr *web3Handler) estimateGas(in *gjson.Result) (interface{}, error) {
}
tx = types.NewTx(&types.LegacyTx{
Nonce: 0,
GasPrice: &big.Int{},
Gas: gasLimit,
GasPrice: big.NewInt(0),
Gas: callMsg.Gas,
To: toAddr,
Value: value,
Data: data,
Value: callMsg.Value,
Data: callMsg.Data,
})
elp, err := svr.ethTxToEnvelope(tx)
if err != nil {
Expand Down Expand Up @@ -1079,18 +1080,15 @@ func (svr *web3Handler) traceTransaction(ctx context.Context, in *gjson.Result)

func (svr *web3Handler) traceCall(ctx context.Context, in *gjson.Result) (interface{}, error) {
var (
err error
contractAddr string
callData []byte
gasLimit uint64
value *big.Int
callerAddr address.Address
err error
callMsg *callMsg
)
blkNumOrHashObj, options := in.Get("params.1"), in.Get("params.2")
callerAddr, contractAddr, gasLimit, _, value, callData, err = parseCallObject(in)
callMsg, err = parseCallObject(in)
if err != nil {
return nil, err
}

var blkNumOrHash any
if blkNumOrHashObj.Exists() {
blkNumOrHash = blkNumOrHashObj.Get("blockHash").String()
Expand Down Expand Up @@ -1130,7 +1128,7 @@ func (svr *web3Handler) traceCall(ctx context.Context, in *gjson.Result) (interf
},
}

retval, receipt, tracer, err := svr.coreService.TraceCall(ctx, callerAddr, blkNumOrHash, contractAddr, 0, value, gasLimit, callData, cfg)
retval, receipt, tracer, err := svr.coreService.TraceCall(ctx, callMsg.From, blkNumOrHash, callMsg.To, 0, callMsg.Value, callMsg.Gas, callMsg.Data, cfg)
if err != nil {
return nil, err
}
Expand Down
76 changes: 62 additions & 14 deletions api/web3server_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,53 +263,83 @@ func parseLogRequest(in gjson.Result) (*filterObject, error) {
return &logReq, nil
}

func parseCallObject(in *gjson.Result) (address.Address, string, uint64, *big.Int, *big.Int, []byte, error) {
type callMsg struct {
From address.Address // the sender of the 'transaction'
To string // the destination contract (empty for contract creation)
Gas uint64 // if 0, the call executes with near-infinite gas
GasPrice *big.Int // wei <-> gas exchange ratio
GasFeeCap *big.Int // EIP-1559 fee cap per gas.
GasTipCap *big.Int // EIP-1559 tip per gas.
Value *big.Int // amount of wei sent along with the call
Data []byte // input data, usually an ABI-encoded contract method invocation

AccessList types.AccessList // EIP-2930 access list.
}

func parseCallObject(in *gjson.Result) (*callMsg, error) {
var (
from address.Address
to string
gasLimit uint64
gasPrice *big.Int = big.NewInt(0)
value *big.Int = big.NewInt(0)
data []byte
err error
from address.Address
to string
gasLimit uint64
gasPrice *big.Int = big.NewInt(0)
gasTipCap *big.Int
gasFeeCap *big.Int
value *big.Int = big.NewInt(0)
data []byte
acl types.AccessList
err error
)
fromStr := in.Get("params.0.from").String()
if fromStr == "" {
fromStr = "0x0000000000000000000000000000000000000000"
}
if from, err = ethAddrToIoAddr(fromStr); err != nil {
return nil, "", 0, nil, nil, nil, err
return nil, err
}

toStr := in.Get("params.0.to").String()
if toStr != "" {
ioAddr, err := ethAddrToIoAddr(toStr)
if err != nil {
return nil, "", 0, nil, nil, nil, err
return nil, err
}
to = ioAddr.String()
}

gasStr := in.Get("params.0.gas").String()
if gasStr != "" {
if gasLimit, err = hexStringToNumber(gasStr); err != nil {
return nil, "", 0, nil, nil, nil, err
return nil, err
}
}

gasPriceStr := in.Get("params.0.gasPrice").String()
if gasPriceStr != "" {
var ok bool
if gasPrice, ok = new(big.Int).SetString(util.Remove0xPrefix(gasPriceStr), 16); !ok {
return nil, "", 0, nil, nil, nil, errors.Wrapf(errUnkownType, "gasPrice: %s", gasPriceStr)
return nil, errors.Wrapf(errUnkownType, "gasPrice: %s", gasPriceStr)
}
}

if gasTipCapStr := in.Get("params.0.maxPriorityFeePerGas").String(); gasTipCapStr != "" {
var ok bool
if gasTipCap, ok = new(big.Int).SetString(util.Remove0xPrefix(gasTipCapStr), 16); !ok {
return nil, errors.Wrapf(errUnkownType, "gasTipCap: %s", gasTipCapStr)
}
}

if gasFeeCapStr := in.Get("params.0.maxFeePerGas").String(); gasFeeCapStr != "" {
var ok bool
if gasFeeCap, ok = new(big.Int).SetString(util.Remove0xPrefix(gasFeeCapStr), 16); !ok {
return nil, errors.Wrapf(errUnkownType, "gasFeeCap: %s", gasFeeCapStr)
}
}

valStr := in.Get("params.0.value").String()
if valStr != "" {
var ok bool
if value, ok = new(big.Int).SetString(util.Remove0xPrefix(valStr), 16); !ok {
return nil, "", 0, nil, nil, nil, errors.Wrapf(errUnkownType, "value: %s", valStr)
return nil, errors.Wrapf(errUnkownType, "value: %s", valStr)
}
}

Expand All @@ -319,7 +349,25 @@ func parseCallObject(in *gjson.Result) (address.Address, string, uint64, *big.In
} else {
data = common.FromHex(in.Get("params.0.data").String())
}
return from, to, gasLimit, gasPrice, value, data, nil

if accessList := in.Get("params.0.accessList"); accessList.Exists() {
acl = types.AccessList{}
log.L().Info("raw acl", zap.String("accessList", accessList.Raw))
if err := json.Unmarshal([]byte(accessList.Raw), &acl); err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal access list %s", accessList.Raw)
}
}
return &callMsg{
From: from,
To: to,
Gas: gasLimit,
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Value: value,
Data: data,
AccessList: acl,
}, nil
}

func (svr *web3Handler) getLogQueryRange(fromStr, toStr string, logHeight uint64) (from uint64, to uint64, hasNewLogs bool, err error) {
Expand Down
76 changes: 59 additions & 17 deletions api/web3server_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/golang/mock/gomock"
"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"

"github.com/iotexproject/iotex-core/v2/test/mock/mock_apicoreservice"
)

func TestParseCallObject(t *testing.T) {
Expand All @@ -18,13 +21,16 @@ func TestParseCallObject(t *testing.T) {
name string
input string

from string
to string
gasLimit uint64
gasPrice *big.Int
value *big.Int
data []byte
err error
from string
to string
gasLimit uint64
gasPrice *big.Int
gasTipCap *big.Int
gasFeeCap *big.Int
value *big.Int
data []byte
acl types.AccessList
err error
}{
{
name: "legacy",
Expand Down Expand Up @@ -62,18 +68,54 @@ func TestParseCallObject(t *testing.T) {
value: new(big.Int).SetInt64(1),
data: []byte{0x6d, 0x4c, 0xe6, 0x3c},
},
{
name: "dynamicfee",
input: `{"params":[{
"from": "0x1a2f3b98e2f5a0f9f9f3f3f3f3f3f3f3f3f3f3f3",
"to": "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
"gas": "0x4e20",
"maxFeePerGas": "0xe8d4a51000",
"maxPriorityFeePerGas": "0xd4a51000",
"value": "0x1",
"input": "0x6d4ce63c",
"accessList": [
{
"address": "0x1a2f3b98e2f5a0f9f9f3f3f3f3f3f3f3f3f3f3f3",
"storageKeys": ["0x0000000000000000000000001a2f3b98e2f5a0f9f9f3f3f3f3f3f3f3f3f3f3f3"]
}
]
},
1]}`,
from: "io1rghnhx8z7ks0n70n70el8uln70el8ulnp8hq9l",
to: "io10sfcvmuj2000083qqd8d6qg7r457vll9gly090",
gasLimit: 20000,
gasPrice: new(big.Int).SetInt64(0),
gasTipCap: new(big.Int).SetInt64(0xd4a51000),
gasFeeCap: new(big.Int).SetInt64(0xe8d4a51000),
value: new(big.Int).SetInt64(1),
data: []byte{0x6d, 0x4c, 0xe6, 0x3c},
acl: types.AccessList{
{
Address: common.HexToAddress("0x1a2f3b98e2f5a0f9f9f3f3f3f3f3f3f3f3f3f3f3"),
StorageKeys: []common.Hash{common.HexToHash("0x0000000000000000000000001a2f3b98e2f5a0f9f9f3f3f3f3f3f3f3f3f3f3f3")},
},
},
},
}

for _, test := range testData {
t.Run(test.name, func(t *testing.T) {
in := gjson.Parse(test.input)
from, to, gasLimit, gasPrice, value, data, err := parseCallObject(&in)
require.Equal(test.from, from.String())
require.Equal(test.to, to)
require.Equal(test.gasLimit, gasLimit)
require.Equal(test.gasPrice, gasPrice)
require.Equal(test.value, value)
require.Equal(test.data, data)
callMsg, err := parseCallObject(&in)
require.Equal(test.from, callMsg.From.String())
require.Equal(test.to, callMsg.To)
require.Equal(test.gasLimit, callMsg.Gas)
require.Equal(test.gasPrice, callMsg.GasPrice)
require.Equal(test.gasTipCap, callMsg.GasTipCap)
require.Equal(test.gasFeeCap, callMsg.GasFeeCap)
require.Equal(test.value, callMsg.Value)
require.Equal(test.data, callMsg.Data)
require.Equal(test.acl, callMsg.AccessList)
require.Equal(test.err, err)
})
}
Expand All @@ -89,7 +131,7 @@ func TestParseCallObject(t *testing.T) {
},
1]}`
in := gjson.Parse(input)
_, _, _, _, _, _, err := parseCallObject(&in)
_, err := parseCallObject(&in)
require.EqualError(err, "gasPrice: unknown: wrong type of params")
})

Expand All @@ -104,7 +146,7 @@ func TestParseCallObject(t *testing.T) {
},
1]}`
in := gjson.Parse(input)
_, _, _, _, _, _, err := parseCallObject(&in)
_, err := parseCallObject(&in)
require.EqualError(err, "value: unknown: wrong type of params")
})

Expand Down

0 comments on commit 9922923

Please sign in to comment.