Solidity Caching Storage Reads
Caching a storage read is copying a state value into a local variable once and working with the copy. The copy is cheap to reuse while the stored value costs more on every read.
A cached value doubles the same as a direct read
Doubling the cached copy gives the same answer as doubling the stored value. The two functions must agree.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CacheValue {
uint256 public total;
function setTotal(uint256 t) public {
total = t;
}
function doubleDirect() public view returns (uint256) {
return total * 2;
}
function doubleCached() public view returns (uint256) {
uint256 cached = total;
return cached * 2;
}
}One cached price serves a whole calculation
The function copies the price once and uses the copy for both results. No second storage read is needed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CachedPrice {
uint256 public price;
function setPrice(uint256 p) public {
price = p;
}
function priceAndDouble() public view returns (uint256 p, uint256 doubled) {
uint256 cached = price;
p = cached;
doubled = cached * 2;
}
}A cached mapping value can be reused
A balance read from a mapping can be cached like any other value. The cached copy is then reused for the doubling.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CachedBalance {
mapping(address => uint256) public balances;
function setBalance(uint256 v) public {
balances[msg.sender] = v;
}
function doubled() public view returns (uint256) {
uint256 cached = balances[msg.sender];
return cached * 2;
}
}Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract RewardPayout {
uint256 public balance;
uint256 public rate;
function set(uint256 b, uint256 r) public {
balance = b;
rate = r;
}
function payout() public view returns (uint256 fee, uint256 net) {
uint256 cachedBalance = balance;
uint256 cachedRate = rate;
fee = cachedBalance * cachedRate / 100;
net = cachedBalance - fee;
}
}Key points
- Cache: a local copy of a state value made once.
- Storage read: each read of state costs more than reading a local variable.
- Reuse: work with the cached copy instead of reading state again.
- Freshness: a cache holds the value from the moment it was copied.
- Use caching to read a value once when a function needs it several times.
In this example, a payout function copies the balance and the rate into local variables once. The fee and the net payout are both worked out from those copies.
Note
a function that changes a cached value must write the result back to storage.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
What does caching a storage read mean?