-
Notifications
You must be signed in to change notification settings - Fork 1
/
error.go
127 lines (108 loc) · 3.29 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package abi
import (
"fmt"
"github.com/defiweb/go-eth/crypto"
)
// Error represents an error in an ABI. The error can be used to decode errors
// returned by a contract call.
type Error struct {
name string
inputs *TupleType
config *ABI
fourBytes FourBytes
signature string
}
// NewError creates a new Error instance.
func NewError(name string, inputs *TupleType) *Error {
return Default.NewError(name, inputs)
}
// ParseError parses an error signature and returns a new Error.
//
// An error signature is similar to a method signature, but returns no values.
// It can be optionally prefixed with the "error" keyword.
//
// The following examples are valid signatures:
//
// foo((uint256,bytes32)[])
// foo((uint256 a, bytes32 b)[] c)
// error foo(tuple(uint256 a, bytes32 b)[] c)
//
// This function is equivalent to calling Parser.ParseError with the default
// configuration.
func ParseError(signature string) (*Error, error) {
return Default.ParseError(signature)
}
// MustParseError is like ParseError but panics on error.
func MustParseError(signature string) *Error {
e, err := ParseError(signature)
if err != nil {
panic(err)
}
return e
}
// NewError creates a new Error instance.
func (a *ABI) NewError(name string, inputs *TupleType) *Error {
m := &Error{
name: name,
inputs: inputs,
config: a,
}
m.generateSignature()
m.calculateFourBytes()
return m
}
// ParseError parses an error signature and returns a new Error.
//
// See ParseError for more information.
func (a *ABI) ParseError(signature string) (*Error, error) {
return parseError(a, signature)
}
// Name returns the name of the error.
func (m *Error) Name() string {
return m.name
}
// Inputs returns the input arguments of the error as a tuple type.
func (m *Error) Inputs() *TupleType {
return m.inputs
}
// FourBytes is the first four bytes of the Keccak256 hash of the error
// signature.
func (m *Error) FourBytes() FourBytes {
return m.fourBytes
}
// Signature returns the error signature, that is, the error name and the
// canonical type of error arguments.
func (m *Error) Signature() string {
return m.signature
}
// Is returns true if the ABI encoded data is an error of this type.
func (m *Error) Is(data []byte) bool {
return m.fourBytes.Match(data)
}
// DecodeValue decodes the error into a map or structure. If a structure is
// given, it must have fields with the same names as error arguments.
func (m *Error) DecodeValue(data []byte, val any) error {
if m.fourBytes.Match(data) {
return fmt.Errorf("abi: selector mismatch for error %s", m.name)
}
return m.config.DecodeValue(m.inputs, data[4:], val)
}
// DecodeValues decodes the error into a map or structure. If a structure is
// given, it must have fields with the same names as error arguments.
func (m *Error) DecodeValues(data []byte, vals ...any) error {
if m.fourBytes.Match(data) {
return fmt.Errorf("abi: selector mismatch for error %s", m.name)
}
return m.config.DecodeValues(m.inputs, data[4:], vals...)
}
// String returns the human-readable signature of the error.
func (m *Error) String() string {
return "error " + m.name + m.inputs.String()
}
func (m *Error) generateSignature() {
m.signature = m.name + m.inputs.CanonicalType()
}
func (m *Error) calculateFourBytes() {
id := crypto.Keccak256([]byte(m.Signature()))
copy(m.fourBytes[:], id[:4])
}