Principles for Parallel-Friendly Contracts
- Minimize shared writes: The scheduler can parallelize transactions that do not write to the same storage keys. Avoid hot globals (e.g., a single counter updated on every call).
- Partition state: Shard storage by user, asset, or id so independent transactions touch disjoint keys.
- Prefer pull over push: Let users claim funds instead of mass-paying recipients in loops.
- Avoid unbounded loops: Especially loops that write to storage or iterate over dynamic arrays/mappings.
- Batch internal work; isolate external effects: Do heavy computation in memory and commit a minimal set of storage writes.
- Use precompiles when available: Precompiles are highly optimized and cheaper than replicating logic in Solidity.
Storage Design Patterns
Partition state by key
Isolate per-user/per-asset data instead of centralizing writes.- Writing a global
totalVolume += amount;in every transaction - Maintaining a single on-chain queue or registry updated by most calls
Prefer pull payments
Avoid writing to many recipients in a single transaction. Emit events and let recipientswithdraw() when needed.
Avoid large storage writes in loops
If you must process many items, keep work in memory and commit a compact result, or split work across multiple transactions keyed by different ids.Gas-Efficient Solidity Practices
- Use
externalfor externally called functions; mark pure/read-only withpure/view. - Pack variables to share storage slots (e.g., multiple
uint8in one slot). - Prefer
bytes32overstringwhen applicable. - Cache array lengths in loops and short-circuit cheap conditions first.
- Use
uncheckedfor arithmetic when overflow is impossible. - Prefer memory over storage for temporary data; commit only final values.
Leverage Sei Precompiles
Sei provides precompiled contracts for common functionality—cheaper and simpler than custom Solidity equivalents: See precompile examples for quick starts.Testing and Analysis
- Use Foundry/Hardhat gas reporters to track changes per function.
- Benchmark under concurrent load to detect hot keys (addresses/ids) that serialize execution.
- Inspect execution with JavaScript tracers and runtime logs.