Detects deployment cost inefficiencies in Solidity: factory patterns that deploy full contracts when ERC-1167 minimal proxies would suffice, non-payable admin functions with unnecessary ETH check overhead, dead code paths inflating bytecode, and opportunities for vanity addresses via CREATE2 for high-frequency contracts. Covers DP-001 (minimal proxy factories), DP-002 (payable admin functions), DP-003 (dead code removal), DP-004 (vanity addresses). Use when writing constructors, factory contracts, or reviewing bytecode size.
npx claudepluginhub zaryab2000/decipher-gas-optimizoor --plugin decipher-gas-optimizoorThis skill is limited to using the following tools:
Identify deployment cost inefficiencies: factory patterns deploying full
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 deployment cost inefficiencies: factory patterns deploying full contracts instead of minimal proxies, dead code inflating bytecode, and configuration-level savings (payable admin functions, vanity addresses for ultra-high-frequency protocols). Deployment cost is 200 gas/byte of bytecode and is paid once per instance — reducing it compounds at factory scale.
new ContractName() patterns| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "It's only one deployment" | Factory contracts deploy potentially thousands of instances; 491,000 gas × 1,000 users = 491M gas wasted | Estimate scale before dismissing |
| "The optimizer removes dead code" | The optimizer eliminates some dead paths but not all — unused internal functions and if(false) branches often survive | Always measure with forge build --sizes before and after |
| "payable is risky" | The risk is locked ETH if no withdrawal exists — document the precondition, don't skip the optimization | Apply with the ETH-recovery check, not instead of it |
| "We can refactor after launch" | Deployment cost is paid at deploy time; you cannot retroactively reduce it for already-deployed instances | Fix the factory pattern before any significant user adoption |
Trigger fires when:
new ContractName() to deploy multiple instancesBash is available to run forge build --sizes for bytecode measurementnew ContractName() for each user? → ERC-1167 minimal
proxy (DP-001, ~491,000 gas saved per clone)payable removes ~24 gas/call
ETH check (DP-002)if(CONSTANT_FALSE) branch or unused internal/private function?
→ remove it (DP-003, 200 gas/byte)Find factory patterns — does it use new ContractName()?
Search the contract for new keywords. For each new deployment, ask:
(a) Are multiple instances of this contract expected? (b) Do all instances
share the same logic (same bytecode)? (c) Do instances only differ in their
initial storage state (set via constructor arguments)?
If yes to all three, the factory is an ERC-1167 minimal proxy candidate
(DP-001). Estimate savings: (full_bytecode_size × 200 gas − 41,000 gas) per
instance. The implementation must be refactored to use initialize() instead
of a constructor.
Find dead code — constant-false branches, unreachable code, unused
private/internal functions.
Look for if (CONSTANT) where the constant is provably false; internal
or private functions with no call sites in the contract; functions
explicitly marked deprecated with no callers. Removing dead code saves
200 gas per byte at deployment — measure with forge build --sizes before
and after. Also flag any code path that the optimizer does not eliminate
(some patterns require explicit removal).
Find non-payable admin functions — would payable save meaningful gas?
For functions with explicit access control (onlyOwner, onlyAdmin) called
frequently, consider whether the ~24 gas/call saving from removing the
msg.value == 0 check justifies the risk. This is a micro-optimization —
apply only after storage, loop, calldata, and struct optimizations are done.
Note: adding payable to a function in a contract with no ETH withdrawal
mechanism risks permanently locking any accidentally sent ETH.
Report each finding with: pattern ID, contract/function, file and line reference, gas estimate, and the exact change required.
Example finding (DP-001):
DP-001 | VaultFactory.sol:12 | VaultFactory.createVault()
Severity : critical
Gas saved : ~491,000 gas per vault deployment
(full Vault ~532,000 gas vs ERC-1167 clone ~41,000 gas)
Before:
function createVault() external returns (address) {
Vault vault = new Vault(msg.sender); // 500,000+ gas per user
vaults.push(address(vault));
return address(vault);
}
After:
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
address public immutable IMPLEMENTATION;
constructor() {
IMPLEMENTATION = address(new VaultImpl()); // deployed once
}
function createVault() external returns (address) {
address clone = Clones.clone(IMPLEMENTATION); // ~41,000 gas
VaultImpl(clone).initialize(msg.sender);
vaults.push(clone);
return clone;
}
Migration: Refactor Vault constructor to initialize() with _initialized
guard. Add _disableInitializers() in VaultImpl constructor (OpenZeppelin
pattern) to prevent initializing the implementation contract itself.
Verify:
forge test --match-test testCreateVault --gas-report
forge test -vvvv # DELEGATECALL visible in clone function calls
Example finding (DP-003):
DP-003 | TokenSale.sol:14 | dead _applyPresaleDiscount() branch
Severity : low
Gas saved : 200 gas/byte × bytecode removed (measure with forge build --sizes)
Issue:
bool public constant IS_PRESALE = false;
function buy(uint256 amount) external payable {
if (IS_PRESALE) {
_applyPresaleDiscount(amount); // dead — IS_PRESALE is false
}
_processPurchase(amount);
}
function _applyPresaleDiscount(uint256 amount) internal pure returns (uint256) {
return amount * 80 / 100; // unreachable internal function
}
Fix: Remove the if (IS_PRESALE) block and _applyPresaleDiscount entirely.
The optimizer may eliminate some dead code — measure before and after.
Verify:
forge build --sizes # bytecode size before vs after
Only read these files when explicitly needed — do not load all three by default:
| File | Read only when… |
|---|---|
resources/PATTERNS.md | You need DP-004 (vanity address via CREATE2) details or full ERC-1167 clone implementation not shown above |
resources/CHECKLIST.md | Producing a formal /decipher-gas-optimizoor:analyze report and confirming all deployment patterns were checked |
resources/EXAMPLE_FINDING.md | Generating a report and needing the exact output format for a factory optimization finding |
docs/evm-gas-reference.md | You need authoritative opcode costs (SSTORE, CREATE, DELEGATECALL) to back a gas estimate |
Example finding (DP-002):
DP-002 | AdminControl.sol:22 | setConfig() non-payable admin function
Severity : low
Gas saved : ~24 gas per call
Context : admin function called ~1,000 times/year — marginal impact
Before:
function setConfig(uint256 value) external {
require(msg.sender == ADMIN);
// ...
}
After:
function setConfig(uint256 value) external payable {
require(msg.sender == ADMIN);
// ...
}
Warning: Only safe if the contract has a mechanism to recover accidentally
sent ETH, or if the admin is trusted not to send ETH accidentally. Apply
only after all higher-priority optimizations are addressed.
Verify:
forge snapshot --diff # ~24 gas reduction per call