When memory is expanded, Vyper uses the calc_mem_gas()
util function to estimate the cost of expansion. However, this calculation should round up to the nearest word, whereas the implementation rounds down to the nearest word. Since gas costs for memory expansion increase exponentially, this can create a substantial deviation as memory sizes get larger.
When Vyper IR is being generated, we estimate the gas cost for all external functions, which includes a specific adjustment for the memory expansion cost:
This calc_mem_gas()
function is implemented as follows:
As we can see on EVM.codes, the calculation should be:
While both implementations use the same formula, the correct implementation uses memory_size_word
as the total number of words of memory that have been touched (ie the memsize is rounded up to the nearest word), whereas the Vyper implementation rounds down to the nearest word.
Gas estimates will consistently underestimate the memory expansion cost of external functions.
Manual Review, EVM.codes
Change the calc_mem_gas()
function to round up to correctly mirror the EVM's behavior:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.