From 1f5e9d66d3b51e4c288644d253f843086440e2c1 Mon Sep 17 00:00:00 2001 From: spencer-tb Date: Thu, 18 Sep 2025 13:07:30 +0100 Subject: [PATCH] chore(deposit): add extra validation for deposit requests. --- core/types/deposit.go | 45 ++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/core/types/deposit.go b/core/types/deposit.go index 8015f29ca7..ae96d6816f 100644 --- a/core/types/deposit.go +++ b/core/types/deposit.go @@ -17,6 +17,7 @@ package types import ( + "encoding/binary" "fmt" ) @@ -27,16 +28,38 @@ const ( // DepositLogToRequest unpacks a serialized DepositEvent. func DepositLogToRequest(data []byte) ([]byte, error) { if len(data) != 576 { - return nil, fmt.Errorf("deposit wrong length: want 576, have %d", len(data)) + return nil, fmt.Errorf("wrong length: want 576, have %d", len(data)) + } + + pubkeyOffset := binary.BigEndian.Uint64(data[24:32]) + withdrawalOffset := binary.BigEndian.Uint64(data[56:64]) + amountOffset := binary.BigEndian.Uint64(data[88:96]) + signatureOffset := binary.BigEndian.Uint64(data[120:128]) + indexOffset := binary.BigEndian.Uint64(data[152:160]) + + if pubkeyOffset != 160 || withdrawalOffset != 256 || amountOffset != 320 || + signatureOffset != 384 || indexOffset != 512 { + return nil, fmt.Errorf("invalid offsets") + } + + pubkeySize := binary.BigEndian.Uint64(data[pubkeyOffset+24 : pubkeyOffset+32]) + withdrawalSize := binary.BigEndian.Uint64(data[withdrawalOffset+24 : withdrawalOffset+32]) + amountSize := binary.BigEndian.Uint64(data[amountOffset+24 : amountOffset+32]) + signatureSize := binary.BigEndian.Uint64(data[signatureOffset+24 : signatureOffset+32]) + indexSize := binary.BigEndian.Uint64(data[indexOffset+24 : indexOffset+32]) + + if pubkeySize != 48 || withdrawalSize != 32 || amountSize != 8 || + signatureSize != 96 || indexSize != 8 { + return nil, fmt.Errorf("invalid field sizes") } request := make([]byte, depositRequestSize) const ( - pubkeyOffset = 0 - withdrawalCredOffset = pubkeyOffset + 48 - amountOffset = withdrawalCredOffset + 32 - signatureOffset = amountOffset + 8 - indexOffset = signatureOffset + 96 + pubkeyRequestOffset = 0 + withdrawalCredRequestOffset = pubkeyRequestOffset + 48 + amountRequestOffset = withdrawalCredRequestOffset + 32 + signatureRequestOffset = amountRequestOffset + 8 + indexRequestOffset = signatureRequestOffset + 96 ) // The ABI encodes the position of dynamic elements first. Since there are 5 // elements, skip over the positional data. The first 32 bytes of dynamic @@ -45,20 +68,20 @@ func DepositLogToRequest(data []byte) ([]byte, error) { // PublicKey is the first element. ABI encoding pads values to 32 bytes, so // despite BLS public keys being length 48, the value length here is 64. Then // skip over the next length value. - copy(request[pubkeyOffset:], data[b:b+48]) + copy(request[pubkeyRequestOffset:], data[b:b+48]) b += 48 + 16 + 32 // WithdrawalCredentials is 32 bytes. Read that value then skip over next // length. - copy(request[withdrawalCredOffset:], data[b:b+32]) + copy(request[withdrawalCredRequestOffset:], data[b:b+32]) b += 32 + 32 // Amount is 8 bytes, but it is padded to 32. Skip over it and the next // length. - copy(request[amountOffset:], data[b:b+8]) + copy(request[amountRequestOffset:], data[b:b+8]) b += 8 + 24 + 32 // Signature is 96 bytes. Skip over it and the next length. - copy(request[signatureOffset:], data[b:b+96]) + copy(request[signatureRequestOffset:], data[b:b+96]) b += 96 + 32 // Index is 8 bytes. - copy(request[indexOffset:], data[b:b+8]) + copy(request[indexRequestOffset:], data[b:b+8]) return request, nil }