Identifies arithmetic operations in Solidity where overflow or underflow is provably impossible and wraps them in unchecked {} blocks to eliminate Solidity 0.8+ overflow guard opcodes (~30 gas per operation). Covers UA-001 (general unchecked arithmetic with proven bounds) and UA-002 (post-comparison unchecked subtraction). Never recommends unchecked without explicit proof of safety. Use when reviewing bounded arithmetic or subtraction that follows a bounds check in Foundry-based Solidity 0.8+ projects.
npx claudepluginhub zaryab2000/decipher-gas-optimizoor --plugin decipher-gas-optimizoorThis skill is limited to using the following tools:
Identify arithmetic operations where the overflow/underflow invariant is provable from
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Identify arithmetic operations where the overflow/underflow invariant is provable from
the surrounding code logic, then wrap those operations in unchecked {} to skip
Solidity 0.8+'s automatic overflow guards (~30 gas per operation). Always require an
explicit inline comment documenting the invariant. Never recommend unchecked without
proof.
Use when:
for conditionuint8 counter that cannot exceed 255)uncheckedDo NOT use for:
| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "This looks safe" | Looking safe is not proof of safety — only bounds proven by code logic count | Document the invariant in an inline comment before applying unchecked |
| "The tests pass" | Tests only cover cases you thought of; unchecked wraps silently on overflow | Add fuzz tests that specifically target boundary conditions |
| "It's a small number" | Small input does not mean overflow-safe — compound expressions can overflow | Trace the maximum possible value through every arithmetic operation |
| "The compiler would catch it" | The compiler does not catch logical overflow errors — it only removes the runtime check | Prove the invariant in code and in comments |
This skill applies when the following markers are present:
File extensions: *.sol
Project markers: foundry.toml or hardhat.config.ts in project root
Language markers:
pragma solidity ^0.8.x; (must be 0.8.0 or higher — overflow checks exist here)contract, library declarations+, -, *, /, ** in function bodiesDo not apply to Solidity < 0.8.0 (no overflow checks present to remove) or to Vyper.
Decision tree — apply in order for each arithmetic operation:
Is the operation in a loop counter increment bounded by the loop condition?
YES → wrap in unchecked {}; add comment; verify with fuzz test (UA-001)
NO ↓
Is the operation a subtraction (a - b)?
YES ↓
Does an immediately preceding if/require prove a >= b in this scope?
YES → wrap in unchecked {}; add comment citing the check (UA-002)
NO → do NOT apply unchecked
NO ↓
Is the operation on values with provable upper/lower bounds from type or constant?
YES → document the invariant; wrap in unchecked {}; add fuzz test (UA-001)
NO → do NOT apply unchecked
| Pattern | Rule | Gas saving |
|---|---|---|
Loop counter i++ bounded by length | UA-001 | ~30 gas/iteration |
a - b where prior check proves a >= b | UA-002 | ~30 gas/subtraction |
| Arithmetic on values bounded by type/constant | UA-001 | ~30 gas/operation |
+, -, *, ** expression in the function under reviewa - b: look for require(a >= b) or if (a < b) revert()
immediately before the operation in the same scopetype(uint256).max?i < length) proves the counter
cannot overflow if length is a uint256 (bounded by type)unchecked {} block stating
exactly why overflow/underflow is impossible// INVARIANT: balance >= amount proven by check above// INVARIANT: i < length from loop condition; i + 1 <= type(uint256).maxforge fuzz to validate no unexpected overflow path existsWhen a safe unchecked opportunity is identified, report using this format:
[MEDIUM] Redundant underflow check after bounds proof — use unchecked subtraction (UA-002) File: src/Escrow.sol, line 18 Estimated saving: ~30 gas per call to withdraw()
Current code:
require(deposits[msg.sender] >= amount, "Insufficient deposit");
deposits[msg.sender] -= amount; // underflow check redundant — already proven above
Optimized code:
uint256 deposit = deposits[msg.sender];
if (deposit < amount) revert InsufficientDeposit();
// INVARIANT: deposit >= amount proven by check above; underflow impossible
unchecked {
deposits[msg.sender] = deposit - amount;
}
Why: Solidity 0.8+ emits an ISZERO + JUMPI sequence after every subtraction to
detect underflow, costing ~30 gas. The require above already proves that
deposits[msg.sender] >= amount. The underflow check on the subtraction is therefore
unreachable dead code. Wrapping in unchecked {} removes it.
Required before applying: Confirm no re-entrancy between the check and the
subtraction (reentrancy guard present or CEI pattern followed). Add fuzz test:
testWithdrawFuzz(uint256 amount) covering amount > deposits[caller].
Only read these files when explicitly needed — do not load all three by default:
| File | Read only when… |
|---|---|
resources/PATTERNS.md | You need a UA-001 edge case (multiplication overflow proof, compound expression bounds) not covered by the Quick Reference |
resources/CHECKLIST.md | Producing a formal /decipher-gas-optimizoor:analyze report and confirming safety checks are complete |
resources/EXAMPLE_FINDING.md | Generating a report and needing the exact format for an unchecked finding |
docs/evm-gas-reference.md | You need the arithmetic opcode cost table (checked vs unchecked ADD/SUB/MUL) to back a gas estimate |