Improve parsing of ETH input data

This commit is contained in:
Martin Boehm 2023-03-02 00:37:33 +01:00
parent 5652ca6b2e
commit a81420fc94
2 changed files with 70 additions and 13 deletions

View File

@ -76,7 +76,8 @@ func decamel(s string) string {
b.WriteByte(' ')
}
b.WriteRune(v)
splittable = unicode.IsLower(v) || unicode.IsNumber(v)
// special handling of ETH to be able to convert "addETHToContract" to "Add ETH To Contract"
splittable = unicode.IsLower(v) || unicode.IsNumber(v) || (i >= 2 && s[i-2:i+1] == "ETH")
}
}
return b.String()
@ -98,7 +99,7 @@ func GetSignatureFromData(data string) uint32 {
const ErrorTy byte = 255
func processParam(data string, index int, t *abi.Type, processed []bool) ([]string, int, bool) {
func processParam(data string, index int, dataOffset int, t *abi.Type, processed []bool) ([]string, int, bool) {
var retval []string
d := index << 6
if d+64 > len(data) {
@ -140,7 +141,7 @@ func processParam(data string, index int, t *abi.Type, processed []bool) ([]stri
for i := 0; i < t.Size; i++ {
var r []string
var ok bool
r, index, ok = processParam(data, index, t.Elem, processed)
r, index, ok = processParam(data, index, dataOffset, t.Elem, processed)
if !ok {
return nil, 0, false
}
@ -156,7 +157,7 @@ func processParam(data string, index int, t *abi.Type, processed []bool) ([]stri
processed[index] = true
index++
offset <<= 1
d = int(offset)
d = int(offset) + dataOffset
dynIndex := d >> 6
if d+64 > len(data) || d < 0 {
return nil, 0, false
@ -195,10 +196,11 @@ func processParam(data string, index int, t *abi.Type, processed []bool) ([]stri
}
}
} else {
newOffset := dataOffset + dynIndex<<6
for i := 0; i < count; i++ {
var r []string
var ok bool
r, dynIndex, ok = processParam(data, dynIndex, t.Elem, processed)
r, dynIndex, ok = processParam(data, dynIndex, newOffset, t.Elem, processed)
if !ok {
return nil, 0, false
}
@ -222,7 +224,7 @@ func tryParseParams(data string, params []string, parsedParams []abi.Type) []bch
var ok bool
for i := range params {
t := &parsedParams[i]
values, index, ok = processParam(data, index, t, processed)
values, index, ok = processParam(data, index, 0, t, processed)
if !ok {
return nil
}
@ -244,7 +246,7 @@ func ParseInputData(signatures *[]bchain.FourByteSignature, data string) *bchain
if len(data) <= 2 { // data is empty or 0x
return &bchain.EthereumParsedInputData{Name: "Transfer"}
}
if len(data) < 10 || (len(data)-10)%64 != 0 {
if len(data) < 10 {
return nil
}
parsed := bchain.EthereumParsedInputData{

View File

@ -112,7 +112,7 @@ func TestParseInputData(t *testing.T) {
Parameters: []string{"address"},
},
{
Name: "addLiquidityETH",
Name: "addLiquidityETHToContract",
Parameters: []string{"address", "uint256", "uint256", "uint256", "address", "uint256"},
},
{
@ -131,6 +131,10 @@ func TestParseInputData(t *testing.T) {
Name: "transmitAndSellTokenForEth",
Parameters: []string{"address", "uint256", "uint256", "uint256", "address", "(uint8,bytes32,bytes32)", "bytes"},
},
{
Name: "execute",
Parameters: []string{"bytes", "bytes[]", "uint256"},
},
}
tests := []struct {
name string
@ -191,13 +195,13 @@ func TestParseInputData(t *testing.T) {
},
},
{
name: "addLiquidityETH",
name: "addLiquidityETHToContract",
signatures: &signatures,
data: "0xf305d719000000000000000000000000b80e5aaa2131c07568128f68b8538ed3c8951234000000000000000000000000000000000000007e37be2022c0914b2680000000000000000000000000000000000000000000007e37be2022c0914b26800000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000009f64b014ca26f2def573246543dd1115b229e4f400000000000000000000000000000000000000000000000000000000623f56f8",
want: &bchain.EthereumParsedInputData{
MethodId: "0xf305d719",
Name: "Add Liquidity ETH",
Function: "addLiquidityETH(address, uint256, uint256, uint256, address, uint256)",
Name: "Add Liquidity ETH To Contract",
Function: "addLiquidityETHToContract(address, uint256, uint256, uint256, address, uint256)",
Params: []bchain.EthereumParsedInputParam{
{
Type: "address",
@ -227,7 +231,7 @@ func TestParseInputData(t *testing.T) {
},
},
{
name: "addLiquidityETH data don't match - too long",
name: "addLiquidityETHToContract data don't match - too long",
signatures: &signatures,
data: "0xf305d719000000000000000000000000b80e5aaa2131c07568128f68b8538ed3c8951234000000000000000000000000000000000000007e37be2022c0914b2680000000000000000000000000000000000000000000007e37be2022c0914b26800000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000009f64b014ca26f2def573246543dd1115b229e4f400000000000000000000000000000000000000000000000000000000623f56f800000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
want: &bchain.EthereumParsedInputData{
@ -235,7 +239,7 @@ func TestParseInputData(t *testing.T) {
},
},
{
name: "addLiquidityETH data don't match - too short",
name: "addLiquidityETHToContract data don't match - too short",
signatures: &signatures,
data: "0xf305d719000000000000000000000000b80e5aaa2131c07568128f68b8538ed3c8951234000000000000000000000000000000000000007e37be2022c0914b2680000000000000000000000000000000000000000000007e37be2022c0914b26800000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000009f64b014ca26f2def573246543dd1115b229e4f4",
want: &bchain.EthereumParsedInputData{
@ -362,6 +366,57 @@ func TestParseInputData(t *testing.T) {
},
},
},
{
name: "execute",
signatures: &signatures,
data: "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000063fd167b00000000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021e19e0c9bab2400000000000000000000000000000000000000000000000000000000000002fa5e9a300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cda4e840411c00a614ad9205caec807c7458a0e3000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
want: &bchain.EthereumParsedInputData{
MethodId: "0x3593564c",
Name: "Execute",
Function: "execute(bytes, bytes[], uint256)",
Params: []bchain.EthereumParsedInputParam{
{
Type: "bytes",
Values: []string{"0x08"},
},
{
Type: "bytes[]",
Values: []string{"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021e19e0c9bab2400000000000000000000000000000000000000000000000000000000000002fa5e9a300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000cda4e840411c00a614ad9205caec807c7458a0e3000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"},
},
{
Type: "uint256",
Values: []string{"1677530747"},
},
},
},
},
{
name: "execute2",
signatures: &signatures,
data: "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000063ffd82300000000000000000000000000000000000000000000000000000000000000020b080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000006f05b59d3b200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000491478480c282e75df8b5700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f0f9d895aca5c8678f706fb8216fa22957685a13",
want: &bchain.EthereumParsedInputData{
MethodId: "0x3593564c",
Name: "Execute",
Function: "execute(bytes, bytes[], uint256)",
Params: []bchain.EthereumParsedInputParam{
{
Type: "bytes",
Values: []string{"0x0b08"},
},
{
Type: "bytes[]",
Values: []string{
"0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000006f05b59d3b20000",
"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000491478480c282e75df8b5700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f0f9d895aca5c8678f706fb8216fa22957685a13",
},
},
{
Type: "uint256",
Values: []string{"1677711395"},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {