Analyze Solidity code for gas optimization opportunities: cached lengths, unchecked arithmetic, custom errors and immuta