The formula in your question describes a gas cost for the total amount of memory allocated in a contract call (i.e. the biggest memory location that contains a nonzero value. Zeroing memory after using it does not decrease the total amount of allocated memory). Note this is in addition to the base 3 gas of an mstore
opcode.
In the above formula, a
is the maximum memory location written to in a contract call. Note that a
is denominated in 32 byte words.
For example, if your contract uses 1,024 bytes of memory, a = 32
.
From the Ethereum yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), the G_memory = 3
.
Putting it all together, the extra gas required by your contract's memory consumption is:
3 * (max_memory / 32) + floor(max_memory^2 / 524,288)
If you use <=724 bytes of memory the second part of this equation is 0. The first term is the linear part of the memory expansion cost (3 times the number of 32-byte words used).
You have to use a very large amount of memory (dozens of kilobytes) for the memory expansion cost to significantly deviate from being linear. Here's a table with some examples:
Memory used (in kb) |
Memory expansion cost |
1 |
98 |
2 |
200 |
4 |
416 |
8 |
896 |
16 |
2048 |
32 |
5120 |
64 |
14336 |
128 |
45056 |
256 |
155648 |
Most contract calls use a few kb at most, making the memory expansion cost small vs the cost of modifying a storage variable.
N.B. It's difficult to see just how much memory a Solidity contract will consume due to memory management being handled by the Solidity compiler. As a general rule of thumb using structs and arrays will increase memory consumption but basic variables like bytes32, uint256
won't. Last time I checked the Solidity compiler does not re-use allocated memory; every time a new memory
variable is created, additional memory will be allocated.