|
|
@ -325,18 +325,17 @@ type Type struct { |
|
|
|
Type string `json:"type"` |
|
|
|
Type string `json:"type"` |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// isArray returns true if the type is a fixed or variable sized array.
|
|
|
|
|
|
|
|
// This method may return false positives, in case the Type is not a valid
|
|
|
|
|
|
|
|
// expression, e.g. "fooo[[[[".
|
|
|
|
func (t *Type) isArray() bool { |
|
|
|
func (t *Type) isArray() bool { |
|
|
|
return strings.HasSuffix(t.Type, "[]") |
|
|
|
return strings.IndexByte(t.Type, '[') > 0 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// typeName returns the canonical name of the type. If the type is 'Person[]', then
|
|
|
|
// typeName returns the canonical name of the type. If the type is 'Person[]' or 'Person[2]', then
|
|
|
|
// this method returns 'Person'
|
|
|
|
// this method returns 'Person'
|
|
|
|
func (t *Type) typeName() string { |
|
|
|
func (t *Type) typeName() string { |
|
|
|
if strings.Contains(t.Type, "[") { |
|
|
|
return strings.Split(t.Type, "[")[0] |
|
|
|
re := regexp.MustCompile(`\[\d*\]`) |
|
|
|
|
|
|
|
return re.ReplaceAllString(t.Type, "") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return t.Type |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Types map[string][]Type |
|
|
|
type Types map[string][]Type |
|
|
@ -387,7 +386,7 @@ func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage |
|
|
|
|
|
|
|
|
|
|
|
// Dependencies returns an array of custom types ordered by their hierarchical reference tree
|
|
|
|
// Dependencies returns an array of custom types ordered by their hierarchical reference tree
|
|
|
|
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string { |
|
|
|
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string { |
|
|
|
primaryType = strings.TrimSuffix(primaryType, "[]") |
|
|
|
primaryType = strings.Split(primaryType, "[")[0] |
|
|
|
|
|
|
|
|
|
|
|
if slices.Contains(found, primaryType) { |
|
|
|
if slices.Contains(found, primaryType) { |
|
|
|
return found |
|
|
|
return found |
|
|
@ -465,53 +464,70 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter |
|
|
|
encType := field.Type |
|
|
|
encType := field.Type |
|
|
|
encValue := data[field.Name] |
|
|
|
encValue := data[field.Name] |
|
|
|
if encType[len(encType)-1:] == "]" { |
|
|
|
if encType[len(encType)-1:] == "]" { |
|
|
|
arrayValue, err := convertDataToSlice(encValue) |
|
|
|
encodedData, err := typedData.encodeArrayValue(encValue, encType, depth) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, dataMismatchError(encType, encValue) |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
buffer.Write(encodedData) |
|
|
|
arrayBuffer := bytes.Buffer{} |
|
|
|
} else if typedData.Types[field.Type] != nil { |
|
|
|
parsedType := strings.Split(encType, "[")[0] |
|
|
|
mapValue, ok := encValue.(map[string]interface{}) |
|
|
|
for _, item := range arrayValue { |
|
|
|
|
|
|
|
if typedData.Types[parsedType] != nil { |
|
|
|
|
|
|
|
mapValue, ok := item.(map[string]interface{}) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
return nil, dataMismatchError(parsedType, item) |
|
|
|
return nil, dataMismatchError(encType, encValue) |
|
|
|
} |
|
|
|
} |
|
|
|
encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) |
|
|
|
encodedData, err := typedData.EncodeData(field.Type, mapValue, depth+1) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
arrayBuffer.Write(crypto.Keccak256(encodedData)) |
|
|
|
buffer.Write(crypto.Keccak256(encodedData)) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) |
|
|
|
byteValue, err := typedData.EncodePrimitiveValue(encType, encValue, depth) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
arrayBuffer.Write(bytesValue) |
|
|
|
buffer.Write(byteValue) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return buffer.Bytes(), nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buffer.Write(crypto.Keccak256(arrayBuffer.Bytes())) |
|
|
|
func (typedData *TypedData) encodeArrayValue(encValue interface{}, encType string, depth int) (hexutil.Bytes, error) { |
|
|
|
} else if typedData.Types[field.Type] != nil { |
|
|
|
arrayValue, err := convertDataToSlice(encValue) |
|
|
|
mapValue, ok := encValue.(map[string]interface{}) |
|
|
|
if err != nil { |
|
|
|
if !ok { |
|
|
|
|
|
|
|
return nil, dataMismatchError(encType, encValue) |
|
|
|
return nil, dataMismatchError(encType, encValue) |
|
|
|
} |
|
|
|
} |
|
|
|
encodedData, err := typedData.EncodeData(field.Type, mapValue, depth+1) |
|
|
|
|
|
|
|
|
|
|
|
arrayBuffer := new(bytes.Buffer) |
|
|
|
|
|
|
|
parsedType := strings.Split(encType, "[")[0] |
|
|
|
|
|
|
|
for _, item := range arrayValue { |
|
|
|
|
|
|
|
if reflect.TypeOf(item).Kind() == reflect.Slice || |
|
|
|
|
|
|
|
reflect.TypeOf(item).Kind() == reflect.Array { |
|
|
|
|
|
|
|
encodedData, err := typedData.encodeArrayValue(item, parsedType, depth+1) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
buffer.Write(crypto.Keccak256(encodedData)) |
|
|
|
arrayBuffer.Write(encodedData) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
byteValue, err := typedData.EncodePrimitiveValue(encType, encValue, depth) |
|
|
|
if typedData.Types[parsedType] != nil { |
|
|
|
|
|
|
|
mapValue, ok := item.(map[string]interface{}) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return nil, dataMismatchError(parsedType, item) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
buffer.Write(byteValue) |
|
|
|
digest := crypto.Keccak256(encodedData) |
|
|
|
|
|
|
|
arrayBuffer.Write(digest) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
bytesValue, err := typedData.EncodePrimitiveValue(parsedType, item, depth) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
arrayBuffer.Write(bytesValue) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return buffer.Bytes(), nil |
|
|
|
} |
|
|
|
|
|
|
|
return crypto.Keccak256(arrayBuffer.Bytes()), nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Attempt to parse bytes in different formats: byte array, hex string, hexutil.Bytes.
|
|
|
|
// Attempt to parse bytes in different formats: byte array, hex string, hexutil.Bytes.
|
|
|
@ -871,7 +887,8 @@ func init() { |
|
|
|
|
|
|
|
|
|
|
|
// Checks if the primitive value is valid
|
|
|
|
// Checks if the primitive value is valid
|
|
|
|
func isPrimitiveTypeValid(primitiveType string) bool { |
|
|
|
func isPrimitiveTypeValid(primitiveType string) bool { |
|
|
|
_, ok := validPrimitiveTypes[primitiveType] |
|
|
|
input := strings.Split(primitiveType, "[")[0] |
|
|
|
|
|
|
|
_, ok := validPrimitiveTypes[input] |
|
|
|
return ok |
|
|
|
return ok |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|