fix: Eth API: accept input data in call arguments under field 'input' (#11505)
The correct name for this field is 'input' according to the Ethereum specs [0]. However, for the longest time, clients have been using 'data' and servers have been lenient to accept both, preferring 'input' over 'data' when both appear. Our lack of support for 'input' had gone unnoticed until go-ethereum decided to adjust their ethclient implementation to issue eth_call and eth_estimateGas requests with the 'input' field instead of 'data' [1]. This suddenly broke apps using this client against Lotus' Eth API. [0]: https://github.com/ethereum/execution-apis/blob/main/src/schemas/transaction.yaml#L33-L35 [1]: ethereum/go-ethereum#28078 Co-authored-by: raulk <raul.kripalani@gmail.com>
This commit is contained in:
parent
1735a6f308
commit
e2712a9157
@ -229,13 +229,25 @@ type EthCall struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *EthCall) UnmarshalJSON(b []byte) error {
|
func (c *EthCall) UnmarshalJSON(b []byte) error {
|
||||||
type TempEthCall EthCall
|
type EthCallRaw EthCall // Avoid a recursive call.
|
||||||
var params TempEthCall
|
type EthCallDecode struct {
|
||||||
|
// The field should be "input" by spec, but many clients use "data" so we support
|
||||||
|
// both, but prefer "input".
|
||||||
|
Input *EthBytes `json:"input"`
|
||||||
|
EthCallRaw
|
||||||
|
}
|
||||||
|
|
||||||
|
var params EthCallDecode
|
||||||
if err := json.Unmarshal(b, ¶ms); err != nil {
|
if err := json.Unmarshal(b, ¶ms); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*c = EthCall(params)
|
|
||||||
|
// If input is specified, prefer it.
|
||||||
|
if params.Input != nil {
|
||||||
|
params.Data = *params.Input
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = EthCall(params.EthCallRaw)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,11 +194,40 @@ func TestMaskedIDInF4(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalEthCall(t *testing.T) {
|
func TestUnmarshalEthCall(t *testing.T) {
|
||||||
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":""}`
|
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFF"}`
|
||||||
|
|
||||||
var c EthCall
|
var c EthCall
|
||||||
err := c.UnmarshalJSON([]byte(data))
|
err := c.UnmarshalJSON([]byte(data))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
require.EqualValues(t, []byte{0xff}, c.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalEthCallInput(t *testing.T) {
|
||||||
|
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","input":"0xFF"}`
|
||||||
|
|
||||||
|
var c EthCall
|
||||||
|
err := c.UnmarshalJSON([]byte(data))
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.EqualValues(t, []byte{0xff}, c.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalEthCallInputAndData(t *testing.T) {
|
||||||
|
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFE","input":"0xFF"}`
|
||||||
|
|
||||||
|
var c EthCall
|
||||||
|
err := c.UnmarshalJSON([]byte(data))
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.EqualValues(t, []byte{0xff}, c.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalEthCallInputAndDataEmpty(t *testing.T) {
|
||||||
|
// Even if the input is empty, it should be used when specified.
|
||||||
|
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFE","input":""}`
|
||||||
|
|
||||||
|
var c EthCall
|
||||||
|
err := c.UnmarshalJSON([]byte(data))
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.EqualValues(t, []byte{}, c.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalEthBytes(t *testing.T) {
|
func TestUnmarshalEthBytes(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user