Lack of constraints specific to transient storage and transaction receipts in the state circuit
Description
In the state circuit, constraints specific to entries of the rw table with tag RwTableTag::AccountTransientStorage and RwTableTag::TxReceipt are missing. The two most important constraints missing due to this were the following:
Constraining the
initial_valuecolumn to be zero in the case ofRwTableTag::AccountTransientStorageConstraining the
state_rootcolumn not to have changed from the previous row in both cases
Even though constraints specific to AccountTransientStorage and TxReceipt are missing, the general constraints still apply. These include the following:
Constraining
not_first_accessConstraining the
valueat a first access read to beinitial_valueConstraining the
valueat other reads to be thevaluein the previous row
Impact
The missing constraint for initial_value to be zero for AccountTransientStorage means that an adversary may set any value. This will then result in the first read of that slot to read this value chosen by the adversary. In some applications, smart contracts may rely critically on transient storage slots being initialized as zero.
Lack of constraints for the state_root column implies an adversary can arbitrarily change the value of state_root in rows of type AccountTransientStorage or TxReceipt. Such a change could then correspond to updating any data stored in the state root, such as the storage of any smart contract address or any account state data.
Recommendations
Implement the missing constraints for AccountTransientStorage and TxReceipt rows in the state circuit.
Remediation
We brought up the lack of constraints specific to RwTableTag::AccountTransientStorage rows in the kick-off call, and the missing constraints were quickly implemented. We then reviewed them as part of our audit. The case of RwTableTag::TxReceipt was out of scope for this audit.
This issue has been acknowledged by Scroll, and a fix was implemented in commit 92d34c51↗.