Detector catalog with before/after examples and risk notes.
Optimization catalog
This catalog documents the detector classes Archon reports today or is structured to support. Detectors should produce concrete before/after guidance and a risk note.
Cache storage reads
Before:
if (positions[id].owner != msg.sender) revert NotOwner();
positions[id].lastUpdated = block.timestamp;
uint256 size = positions[id].size;After:
Position storage position = positions[id];
if (position.owner != msg.sender) revert NotOwner();
position.lastUpdated = block.timestamp;
uint256 size = position.size;Impact: reduces repeated mapping lookups and storage access overhead. Risk: low when the storage reference points to the same slot.
Use calldata for read-only external parameters
Before:
function batch(address[] memory users) external {After:
function batch(address[] calldata users) external {Impact: avoids copying dynamic arrays into memory. Risk: low if the function only reads the array.
Custom errors instead of revert strings
Before:
require(msg.sender == owner, "only owner");After:
if (msg.sender != owner) revert OnlyOwner();Impact: smaller bytecode and cheaper reverts. Risk: client code that parses revert strings must be updated.
Pack storage variables
Before:
uint256 feeBps;
bool paused;
address treasury;After:
address treasury;
uint96 feeBps;
bool paused;Impact: can reduce storage slots. Risk: high in upgradeable contracts because storage layout changes can corrupt state.
Remove duplicate event payload
Before:
emit ProofSubmitted(msg.sender, proof, keccak256(proof));After:
emit ProofSubmitted(msg.sender, keccak256(proof));Impact: can reduce DA/log bytes on Mantle. Risk: indexers that depend on the raw proof event data must fetch it elsewhere.
Avoid redundant external calls
Before:
uint256 assets = vault.totalAssets();
uint256 shares = vault.convertToShares(assets);
uint256 again = vault.totalAssets();After:
uint256 assets = vault.totalAssets();
uint256 shares = vault.convertToShares(assets);
uint256 again = assets;Impact: saves call overhead. Risk: unsafe if the external state can change between calls due to callbacks or intentional freshness requirements.



