diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index ff74e08793..1002a5b3e6 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -375,6 +375,16 @@ func TypedDataAndHash(typedData TypedData) ([]byte, string, error) { return crypto.Keccak256([]byte(rawData)), rawData, nil } +// WeakHashStruct generates a keccak256 hash of the encoding of the provided data +// WeakHashStruct use WeakEncodeData to encodeData, in which it will encode non-provided struct params with zerohash +func (typedData *TypedData) WeakHashStruct(primaryType string, data TypedDataMessage) (hexutil.Bytes, error) { + encodedData, err := typedData.WeakEncodeData(primaryType, data, 1) + if err != nil { + return nil, err + } + return crypto.Keccak256(encodedData), nil +} + // HashStruct generates a keccak256 hash of the encoding of the provided data func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage) (hexutil.Bytes, error) { encodedData, err := typedData.EncodeData(primaryType, data, 1) @@ -440,11 +450,25 @@ func (typedData *TypedData) TypeHash(primaryType string) hexutil.Bytes { return crypto.Keccak256(typedData.EncodeType(primaryType)) } +// EncodeData generates the following encoding: +// `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)` +// +// each encoded member is 32-byte long +// Will encode missing params with zerohash instead of throwing error +// This behavior is to match Browser's eth_signTypedData_v4 +func (typedData *TypedData) WeakEncodeData(primaryType string, data map[string]interface{}, depth int) (hexutil.Bytes, error) { + return typedData.encodeData(primaryType, data, depth, true) +} + // EncodeData generates the following encoding: // `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)` // // each encoded member is 32-byte long func (typedData *TypedData) EncodeData(primaryType string, data map[string]interface{}, depth int) (hexutil.Bytes, error) { + return typedData.encodeData(primaryType, data, depth, false) +} + +func (typedData *TypedData) encodeData(primaryType string, data map[string]interface{}, depth int, weakVerify bool) (hexutil.Bytes, error) { if err := typedData.validate(); err != nil { return nil, err } @@ -477,7 +501,7 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter if !ok { return nil, dataMismatchError(parsedType, item) } - encodedData, err := typedData.EncodeData(parsedType, mapValue, depth+1) + encodedData, err := typedData.encodeData(parsedType, mapValue, depth+1, weakVerify) if err != nil { return nil, err } @@ -493,7 +517,7 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter buffer.Write(crypto.Keccak256(arrayBuffer.Bytes())) } else if typedData.Types[field.Type] != nil { - if encValue == nil { + if encValue == nil && weakVerify { buffer.Write(common.Hash{}.Bytes()) continue } @@ -501,7 +525,7 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter if !ok { return nil, dataMismatchError(encType, encValue) } - encodedData, err := typedData.EncodeData(field.Type, mapValue, depth+1) + encodedData, err := typedData.encodeData(field.Type, mapValue, depth+1, weakVerify) if err != nil { return nil, err } diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go index b817d2be29..67c659cb12 100644 --- a/signer/core/signed_data_test.go +++ b/signer/core/signed_data_test.go @@ -359,15 +359,15 @@ func TestEncodeData(t *testing.T) { } } -func TestEncodeDataWithMissingParams(t *testing.T) { +func TestWeakEncodeData(t *testing.T) { t.Parallel() - hash, err := typedData.EncodeData(typedDataWithMissing.PrimaryType, typedDataWithMissing.Message, 0) + hash, err := typedData.WeakEncodeData(typedDataWithMissing.PrimaryType, typedDataWithMissing.Message, 0) if err != nil { t.Fatal(err) } dataEncoding := fmt.Sprintf("0x%s", common.Bytes2Hex(hash)) if dataEncoding != "0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac20000000000000000000000000000000000000000000000000000000000000000cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8" { - t.Errorf("Expected different encodeData result (got %s)", dataEncoding) + t.Errorf("Expected different weakEncodeData result (got %s)", dataEncoding) } }