Closed c4-bot-5 closed 4 months ago
saxenism (sponsor) disputed
Invalid issue since hash functions has paddings that’s why the cost per 40 bytes is the same as the cost per 136 bytes
alex-ppg marked the issue as unsatisfactory: Invalid
alex-ppg marked the issue as duplicate of #38
Lines of code
https://github.com/code-423n4/2024-03-zksync/blob/4f0ba34f34a864c354c7e8c47643ed8f4a250e13/code/system-contracts/contracts/L1Messenger.sol#L44-L64
Vulnerability details
Proof of Concept
First take a look at https://github.com/code-423n4/2024-03-zksync/blob/4f0ba34f34a864c354c7e8c47643ed8f4a250e13/code/system-contracts/contracts/L1Messenger.sol#L44-L64
Evidently there are constants placed and protocol have used the logic of adding one after the division so as to sort out issues where the numerator is "<" than the denominator causing the equation to return 0, case is that this logic is somewhat wrong and could be very harmful to some users.
Now consider the three instances where it's calculated, i.e in sendL2ToL1Log()
In sendToL1()
And lastly in requestBytecodeL1Publication()
Evidently, in all three instances, we can see that there is a constant query on
keccakGasCost(64)
which would always return40
due to the rounding down in the calculation, this is cause64
is <KECCAK_ROUND_NUMBER_OF_BYTES = 136
, to put this in perspective, if 64 was replaced with double it's value, i.e 128, it would still return40
indicating that users are charged in this case more than double what they were supposed to be charged, with the increment being ~ 110.9% of increment, from the keccak gas calculation we can see that this is the original increment in monetary value only forrequestBytecodeL1Publication()
, because the remaining instances in bothsendL2ToL1Log()
andsendToL1()
still multiply on this value, i.e in the former the returned value is being doubled where as in the latter it's being tripled (where as the percentage increment is still the same for all instances it's important to still note this cause in their monetary value this is more weight on the users in the latter two instances).Now keeping the constant query to
keccakGasCost(64)
aside, the below are also done in the calculations.sendL2ToL1Log()
andsendToL1()
,keccakGasCost()
is also queried again with theL2_TO_L1_LOG_SERIALIZE_SIZE
, keeping in mind that the value of this variable is 88 this leads to an additional ~ 55% on the cost of calculating the keccak256.requestBytecodeL1Publication()
, is the only place wheresha256GasCost()
is also queried which has the same division and then+ 1
logic which means that depending on thebytecodeLen
value this calculation would also overcharge users.Impact
Users are overcharged gas for hashing in different instances in as much as there is a need to publishh pubdata , sometimes even more than triple the amount really needed to execute the hashing attached with their transactions, this amount overcharged can't also be considered that it's for the compensation of the operator's storage cause the
gasToPay
calculation already includesCOMPUTATIONAL_PRICE_FOR_PUBDATA * pubdataLen
that takes care of that.Recommended Mitigation Steps
Consider reimplementing the logic in the formular used to calculate the gas cost for hashing in
keccakGasCost
andkeccakGasCost
to not overcharge users.Assessed type
Context