Skip to content

Commit

Permalink
Merge pull request #82 from hyperledger/err-strings
Browse files Browse the repository at this point in the history
Add utility for parsing errors, including as a string
  • Loading branch information
EnriqueL8 authored Oct 7, 2024
2 parents 7345fe7 + eb284ce commit 0b9dbf8
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 4 deletions.
50 changes: 50 additions & 0 deletions pkg/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,56 @@ func (a ABI) Errors() map[string]*Entry {
return m
}

// Returns the components value from the parsed error
func (a ABI) ParseError(revertData []byte) (*Entry, *ComponentValue, bool) {
return a.ParseErrorCtx(context.Background(), revertData)
}

// Returns the components value from the parsed error
func (a ABI) ParseErrorCtx(ctx context.Context, revertData []byte) (*Entry, *ComponentValue, bool) {
// Always include the default error
a = append(ABI{
{Type: Error, Name: "Error", Inputs: ParameterArray{{Name: "reason", Type: "string"}}},
}, a...)
for _, e := range a {
if e.Type == Error {
if cv, err := e.DecodeCallDataCtx(ctx, revertData); err == nil {
return e, cv, true
}
}
}
return nil, nil, false
}

func (a ABI) ErrorString(revertData []byte) (string, bool) {
return a.ErrorStringCtx(context.Background(), revertData)
}

func (a ABI) ErrorStringCtx(ctx context.Context, revertData []byte) (string, bool) {
var parsed []interface{}
e, cv, ok := a.ParseErrorCtx(ctx, revertData)
if ok {
if res, err := NewSerializer().SetFormattingMode(FormatAsFlatArrays).SerializeInterfaceCtx(ctx, cv); err == nil {
parsed, ok = res.([]interface{})
}
}
if !ok || parsed == nil {
return "", false
}
buff := new(bytes.Buffer)
buff.WriteString(e.Name)
buff.WriteRune('(')
for i, c := range parsed {
if i > 0 {
buff.WriteRune(',')
}
b, _ := json.Marshal(c)
buff.Write(b)
}
buff.WriteRune(')')
return buff.String(), true
}

// Validate processes all the components of all the parameters in this ABI entry
func (e *Entry) Validate() (err error) {
return e.ValidateCtx(context.Background())
Expand Down
45 changes: 45 additions & 0 deletions pkg/abi/abi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1027,3 +1027,48 @@ func TestComplexStructSolidityDef(t *testing.T) {
}, childStructs)

}

func TestErrorString(t *testing.T) {

customErrABI := ABI{
{
Type: Error,
Name: "ExampleError",
Inputs: ParameterArray{
{
Name: "param1",
Type: "string",
},
{
Name: "param2",
Type: "uint256",
},
},
},
}

revertReason, err := customErrABI[0].EncodeCallDataJSON([]byte(`{"param1":"test1","param2":12345}`))
assert.NoError(t, err)

errString, ok := customErrABI.ErrorString(revertReason)
assert.True(t, ok)
assert.Equal(t, `ExampleError("test1","12345")`, errString)

e, cv, ok := customErrABI.ParseError(revertReason)
assert.True(t, ok)
assert.NotNil(t, e)
assert.NotNil(t, cv)

exampleDefaultError := ethtypes.MustNewHexBytes0xPrefix(`0x08c379a0` +
`0000000000000000000000000000000000000000000000000000000000000020` +
`000000000000000000000000000000000000000000000000000000000000001a` +
`4e6f7420656e6f7567682045746865722070726f76696465642e000000000000`)
errString, ok = customErrABI.ErrorString(exampleDefaultError)
assert.True(t, ok)
assert.Equal(t, `Error("Not enough Ether provided.")`, errString)

mismatchError := ethtypes.MustNewHexBytes0xPrefix(`0x11223344`)
_, ok = customErrABI.ErrorString(mismatchError)
assert.False(t, ok)

}
6 changes: 3 additions & 3 deletions pkg/abi/signedi256.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ var posMax = map[uint16]*big.Int{}
var negMax = map[uint16]*big.Int{}

func init() {
for i := 8; i <= 256; i += 8 {
posMax[uint16(i)] = maxPositiveSignedInt(uint(i))
negMax[uint16(i)] = maxNegativeSignedInt(uint(i))
for i := uint16(8); i <= uint16(256); i += 8 {
posMax[i] = maxPositiveSignedInt(uint(i))
negMax[i] = maxNegativeSignedInt(uint(i))
}
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/abi/typecomponents.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ func parseMSuffix(ctx context.Context, abiTypeString string, ec *typeComponent,
if err != nil {
return i18n.WrapError(ctx, err, signermsgs.MsgInvalidABISuffix, abiTypeString, ec.elementaryType)
}
//nolint:gosec // we used bitSize on ParseUint above
ec.m = uint16(val)
if ec.m < ec.elementaryType.mMin || ec.m > ec.elementaryType.mMax {
return i18n.NewError(ctx, signermsgs.MsgInvalidABISuffix, abiTypeString, ec.elementaryType)
Expand All @@ -646,6 +647,7 @@ func parseNSuffix(ctx context.Context, abiTypeString string, ec *typeComponent,
if err != nil {
return i18n.WrapError(ctx, err, signermsgs.MsgInvalidABISuffix, abiTypeString, ec.elementaryType)
}
//nolint:gosec // we used bitSize on ParseUint above
ec.n = uint16(val)
if ec.n < ec.elementaryType.nMin || ec.n > ec.elementaryType.nMax {
return i18n.NewError(ctx, signermsgs.MsgInvalidABISuffix, abiTypeString, ec.elementaryType)
Expand All @@ -672,10 +674,11 @@ func parseMxNSuffix(ctx context.Context, abiTypeString string, ec *typeComponent

// parseArrayM parses the "8" in "uint256[8]" for a fixed length array of <type>[M]
func parseArrayM(ctx context.Context, abiTypeString string, ac *typeComponent, mStr string) error {
val, err := strconv.ParseUint(mStr, 10, 64)
val, err := strconv.ParseUint(mStr, 10, 32)
if err != nil {
return i18n.WrapError(ctx, err, signermsgs.MsgInvalidABIArraySpec, abiTypeString)
}
//nolint:gosec // we used bitSize on ParseUint above
ac.arrayLength = int(val)
return nil
}
Expand Down

0 comments on commit 0b9dbf8

Please sign in to comment.