diff --git a/sdk/vaa/structs.go b/sdk/vaa/structs.go index 23b0495e1..be2957145 100644 --- a/sdk/vaa/structs.go +++ b/sdk/vaa/structs.go @@ -368,13 +368,18 @@ func Unmarshal(data []byte) (*VAA, error) { return nil, fmt.Errorf("failed to read commitment: %w", err) } - payload := make([]byte, InternalTruncatedPayloadSafetyLimit) - n, err := reader.Read(payload) - if err != nil || n == 0 { - return nil, fmt.Errorf("failed to read payload [%d]: %w", n, err) - } + // Make sure to only read the payload if the VAA has one; VAAs may have a 0 length payload + if reader.Len() != 0 { + payload := make([]byte, InternalTruncatedPayloadSafetyLimit) + n, err := reader.Read(payload) + if err != nil { + return nil, fmt.Errorf("failed to read payload [%d]: %w", n, err) + } - v.Payload = payload[:n] + v.Payload = payload[:n] + } else { + v.Payload = []byte{} + } return v, nil } diff --git a/sdk/vaa/structs_test.go b/sdk/vaa/structs_test.go index e7175e32c..e965cd89c 100644 --- a/sdk/vaa/structs_test.go +++ b/sdk/vaa/structs_test.go @@ -198,6 +198,24 @@ func getVaa() VAA { } } +func getEmptyPayloadVaa() VAA { + var payload = []byte{} + var governanceEmitter = Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4} + + return VAA{ + Version: uint8(1), + GuardianSetIndex: uint32(1), + Signatures: []*Signature{}, + Timestamp: time.Unix(0, 0), + Nonce: uint32(1), + Sequence: uint64(1), + ConsistencyLevel: uint8(32), + EmitterChain: ChainIDSolana, + EmitterAddress: governanceEmitter, + Payload: payload, + } +} + func TestAddSignature(t *testing.T) { vaa := getVaa() @@ -256,6 +274,14 @@ func TestUnmarshal(t *testing.T) { assert.Equal(t, &vaa1, vaa2) } +func TestUnmarshalNoPayload(t *testing.T) { + vaaBytes := []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20} + vaa1 := getEmptyPayloadVaa() + vaa2, err := Unmarshal(vaaBytes) + assert.Nil(t, err) + assert.Equal(t, &vaa1, vaa2) +} + func TestUnmarshalTooBig(t *testing.T) { vaa := getVaa()