TL;DR

Current Explicit Limits

We are currently constrained by MAX_ADD_PIECES_EXTRA_DATA_SIZE = 8192 in FWSS. This constant intentionally limits the extraData parameter for the addPieces operation. extraData caries the client's signature, nonce and the metadata associated with all pieces being added.

This limit creates a theoretical max of 61 pieces with empty metadata and when every piece carries the full allowed metadata we reach a theoretical cap of 5 pieces.

This existing cap is enforced in two places: FWSS MAX_ADD_PIECES_EXTRA_DATA_SIZE and Curio MaxAddPiecesExtraDataSize (the SDK has no cap and currently relies on Curio rejection for erroring).

Further we constrain the metadata within extraData in the following ways:

But there are additional bounds that come into play that even stop us from reaching the 61 piece theoretical max. The effective cap is the smallest of these: with no or light metadata we are event-bound at 41, with heavy metadata we are message-bound at around 37, and on mainnet gas is a soft ceiling on top (made worse by the create-and-add combo, below).

Actual Implicit Limits

FVM per-event value limit (MAX_TOTAL_VALUES_LEN = 8192 B)

This bites us in PDPVerifier's PiecesAdded which doesn't even use extraData. They look like this: event PiecesAdded(uint256 indexed setId, uint256[] pieceIds, Cids.Cid[] pieceCids). A PieceCIDv2 is 39 raw bytes, but abi.encode of Cid[] (a dynamic array of struct { bytes data }) inflates each one to 160 bytes, and the parallel pieceIds array adds another 32 each for a total of 192 bytes per piece. Cid[] is a dynamic array of tuples, so for each element we have a 32-byte offset, a 32-byte tuple inner offset (the bytes inner), a 32-byte bytes word length specifier (always 39) and the actual CID bytes which is 39 but has to be padded up to 64-bytes to fit.