Optimizing Storage
Storage optimization in Solidity smart contracts is an essential consideration given the relatively high costs associated with writing data to the blockchain. Every write operation has a gas fee, and more extensive storage usage equates to increased deployment and execution costs. The peaq network provides EVM compatibility, so the same best practices that apply to Ethereum also apply here—but within peaq’s unique economy and infrastructure.
Key topics covered in this guide include:
- How the EVM (on peaq) stores data in 256-bit storage slots.
- Why mappings can be more efficient than arrays in certain scenarios.
- Additional strategies like data packing, using
bytes
effectively, and using events instead of on-chain storage. - Practical coding examples in Solidity.
Prerequisites
- Basic Solidity Knowledge
- An understanding of how the EVM handles storage, memory, and call data, as well as the associated gas costs for these operations.
- Familiar that peaq network is EVM-compatible and that the best practices for storage optimization hold true in its environment, with potential additional benefits from the underlying Substrate-based infrastructure.
Optimizations
Below are some high-level strategies and examples to help you optimize your smart contract storage usage on the peaq network’s EVM.
Use Mappings Instead of Arrays (When Feasible)
Arrays (especially dynamic arrays) often require more operations to manage (e.g., iteration, boundary checks) and can grow unbounded if not carefully restricted. Mappings store data more sparsely, saving storage when you do not need sequential elements.
Explanation:
- In the above example,
TestMapping
is more flexible with sparse data and can save gas. - You can maintain a separate counter (
itemCount
) to track indices, mimicking array-like behavior.
Use the Right Data Types and Pack Them
The EVM stores data in 256-bit slots. When two or more variables fit into a single 256-bit slot, they can be packed together to reduce overall storage usage.
Best Practice:
- Group smaller types together so they can occupy the same slot.
- Reordering the variables to minimize wasted space in each 256-bit slot can substantially reduce gas costs.
Store Data Off-Chain or Use Events When Appropriate
If you only need data for historical or informational purposes (i.e., you don’t need it to stay in contract storage for on-chain logic), consider storing it off-chain or emitting it in events. Events are cheaper than storing data on-chain and still let you retrieve the data from transaction logs.
Note:
- Data in events is not accessible to contracts directly (only via off-chain indexing), so only move data to events if your contract does not need to rely on it for future state changes.
- Checkout our indexing solutions to see how to query these events.
Consider Using bytes
Arrays for Packed Storage
In some scenarios (especially with strings or variable-length data), storing in a single bytes
array can be more efficient than storing an array of fixed-size data types, as it packs data continuously without leaving empty space.
Carefully Manage Storage Reads and Writes
Each storage write operation costs gas, so optimizing writes—and reducing the number of expensive SSTORE
operations—can lower costs.
Strategies:
- Minimize writes by caching frequently updated values in memory and writing only once when necessary.
- Use local variables (memory) rather than reading from storage multiple times in a function. Each storage read is more expensive than a memory read.
Reset Storage Slots to Zero When Possible
The EVM provides a gas refund for clearing storage slots (i.e., writing zero to a previously non-zero slot). Although refunds are capped, this can still result in net savings when performing large transactions.
Use Structs Wisely
Grouping related variables into structs can help you manage your data more systematically. However, remember that each struct field occupies storage in 256-bit slots, and you can still leverage the same packing principles within a struct.
Summary
Optimizing storage in Solidity smart contracts not only reduces gas costs for your end-users but also contributes to the overall efficiency of the peaq network. By adopting these best practices—using mappings, packing data, leveraging events instead of persistent storage, and resetting unused slots—you can ensure your dApps remain economical and performant.
Key Takeaways:
- Mappings often outperform arrays, especially for sparse data.
- Data Packing aligns smaller data types to minimize wasted storage space.
- Events are a cheaper alternative to on-chain storage if you only need data for off-chain retrieval.
- Minimizing Writes to contract storage lowers gas costs significantly.
- Storage Slot Cleanup can yield gas refunds and improve contract efficiency.
As you develop on the peaq network’s EVM, keep these strategies in mind to create secure, cost-effective, and efficient smart contracts. By following these guidelines, you will optimize your contracts’ storage usage, reducing costs and enhancing the user experience for your dApps.