Assessment reports>Brevis>Informational findings>Low bit widths for ,Transaction, fields
Category: Coding Mistakes

Low bit widths for Transaction fields

Informational Severity
Informational Impact
N/A Likelihood

Description

The Transaction struct is defined in sdk/circuit_input.go as follows:

type Transaction struct {
	ChainId  Uint248
	BlockNum Uint32
	Nonce    Uint248
	// GasTipCapOrGasPrice is GasPrice for legacy tx (type 0) and GasTipCapOap for
	// dynamic-fee tx (type 2)
	GasTipCapOrGasPrice Uint248
	// GasFeeCap is always 0 for legacy tx
	GasFeeCap Uint248
	GasLimit  Uint248
	From      Uint248
	To        Uint248
	Value     Bytes32
}

It is intended to reflect the data associated to an Ethereum transaction. The Ethereum yellow paper (version 9fde3f4 from September 2nd, 2024) specifies the fields associated to a transaction in section 4.2. The types of most of the fields of the above struct are specified in display (18) of the yellow paper, as follows:

  • Nonce — 256-bit unsigned integer

  • GasTipCapOrGasPrice — 256-bit unsigned integer

  • GasFeeCap — 256-bit unsigned integer

  • GasLimit — 256-bit unsigned integer

  • To — 20-byte address or empty

  • Value — 256-bit unsigned integer

Apart from To and Value, where the type in the struct above is sufficient to represent the entire range specified in the yellow paper, the other fields listed above are specified as 256-bit unsigned integers, but the struct only stores them as 248-bit unsigned integers. The gas-related values should in practice never become large enough to not fit into 248, though. The nonce is the number of transactions sent by the sender so far. It is not feasible to reach transactions on an account, so this value also fits in practice into 248 bits.

This leaves From, ChainId, and BlockNum. The block number is not a part of the transaction in the Ethereum specification, but transactions are part of a block with a block number, specified in section 4.4, and in display (44) as a natural number of arbitrary size. In practice, it will take more than years until the Ethereum block number exhausts 248 bits, so this field is not a problem either. The From field is not part of the transaction in the Ethereum specification but derived from the signature, but as addresses on Ethereum are 160 bits large, 248 bits suffice for From as well.

It remains to discuss ChainId. For the transaction, the Ethereum specification only specifies that the chain ID should be to the network's chain ID, which is 1 in the case of Ethereum Mainnnet. EIP-155, which introduced the chain ID, did not specify a maximum size. EIP-1344 suggests that the chain ID is a 256-bit value. There was some discussion (see for example on GitHub here or on Ethereum Magicians here) to restrict the range, but nothing passed by the time this report was written, as far as we are aware.

There are some suggestions that chain IDs may be generated as hashes, in which case chain IDs not fitting in 248 bits would be realistic. However, the actual range for the chain IDs in Brevis is restricted further. The pack function restricts ChainId to only 32 bits. There are already chains with chain IDs that are larger than 32 bits.

Impact

The current circuits will not be usable for transaction on chains with a chain ID equal to or bigger than .

Recommendations

Should Brevis wish to be usable for such chains, the bit width allowed for ChainID would need to be increased. Alternatively, we recommend to document as a comment in the code that it is an explicit choice.

Remediation

Brevis is planning to remove ChainId in a future iteration of Brevis SDK.

Zellic © 2025Back to top ↑