AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Solady Erc20 Permit2 Assumptions

skill-omermaksutii-rugproof-solady-erc20-permit2-assumptions · by omermaksutii

Detect unsafe assumptions about Solady's gas-optimized ERC20/ERC2612 permit and DN404 metadata. Solady's ERC20 uses custom storage slots, returns bools via assembly, exposes a virtual `_constantNameHash`/`_versionHash` for permit domain separation, and its DN404 mirror splits ERC20/ERC721 logic — integrators that assume OZ-style behavior, revert strings, or that `name()`/`decimals()` are always p…

No reviews yet
0 installs
17 views
0.0% view→install

Install

$ agentstack add skill-omermaksutii-rugproof-solady-erc20-permit2-assumptions

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-omermaksutii-rugproof-solady-erc20-permit2-assumptions)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Solady Erc20 Permit2 Assumptions? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Solady ERC20 / permit / DN404 assumption detection

When this applies

Trigger on any of:

  • import {ERC20} from "solady/tokens/ERC20.sol"; or ERC2612, DN404, DN404Mirror, ERC4626 from solady
  • Integrations calling permit(...) and assuming a fixed EIP-712 domain / version string
  • Code relying on Solady's revert reasons (Solady reverts with custom errors / 4-byte selectors, not strings)
  • DN404 tokens treated as plain ERC20 (the NFT mirror has separate transfer semantics)
  • Off-chain indexers decoding events / revert data assuming OZ layout
  • Overriding name(), symbol(), _constantNameHash, _versionHash, or _domainNameAndVersion

Detection patterns

Hardcoded permit domain separator (MEDIUM)

bytes32 DOMAIN = keccak256(abi.encode(
    TYPE_HASH, keccak256("MyToken"), keccak256("1"), block.chainid, token
));
// ← assumes version "1"; Solady ERC2612 default version is "1" but DN404/overrides may differ

Solady derives the domain via _domainNameAndVersion() (default version "1"). If the token overrides _versionHash or name(), a hand-rolled separator mismatches and every permit reverts InvalidPermit. Signal: off-chain or on-chain code reconstructs the EIP-712 domain instead of reading DOMAIN_SEPARATOR() from the token.

Relying on revert strings (MEDIUM)

try token.transferFrom(a, b, amt) returns (bool) {}
catch Error(string memory reason) {           // ← Solady reverts with custom errors,
    if (keccak256(bytes(reason)) == ...) {}    //    NOT Error(string); this branch never hits
}

Solady reverts InsufficientBalance() / InsufficientAllowance() (4-byte). catch Error(string) won't match; only catch (bytes memory) / catch will. Signal: catch Error(string) or string comparison used to branch on a Solady token failure.

DN404 treated as vanilla ERC20 (MEDIUM)

dn404Token.transfer(to, amt);   // also mints/burns NFTs in the mirror; gas + reentrancy surface

DN404 fractionalizes an NFT collection; an ERC20 transfer can mint/burn mirror NFTs and invoke onERC721Received-style hooks. Treating it as inert ERC20 ignores added gas and a callback surface. Signal: DN404 token integrated through a path that assumes ERC20 transfers have no side effects / no callbacks.

Assuming metadata always present (LOW-MEDIUM)

uint8 d = IERC20(token).decimals();   // Solady ERC20 leaves name/symbol/decimals virtual

Solady's base ERC20 leaves name()/symbol() as virtual returning empty unless overridden; a minimal token may omit them. Signal: unguarded decimals()/name() read on a Solady-derived token.

Severity rubric

| Pattern | Severity | Notes | |---|---|---| | Hand-rolled permit domain mismatching token → permits brick | Medium | Liveness, not loss; per-token | | Revert-string branching never executes | Medium | Silent wrong control flow | | DN404 used as plain ERC20 (callback / gas surprise) | Medium | Reentrancy/gas surface, see [[reentrancy]] | | Unguarded metadata read | Low | Reverts or returns empty |

Remediation patterns

  1. Read DOMAIN_SEPARATOR() off the token instead of reconstructing it; never hardcode the version string.
  2. Catch bytes, not Error(string) — match Solady custom-error selectors or use a generic catch.
  3. Detect DN404 (e.g. via DN404Mirror linkage / interface) and route it through NFT-aware logic; budget gas and treat transfers as callback-bearing.
  4. Guard metadata with try/catch defaulting decimals to 18.

False-positive notes

  • Reading DOMAIN_SEPARATOR() directly (not reconstructing it) is correct — no finding.
  • A non-DN404 Solady ERC20 with metadata overridden is a normal token — only flag missing overrides.
  • Generic catch {} already handles custom errors — downgrade.

Related

  • [[signature-malleability]] — permit signature handling
  • [[token-compatibility]] — non-standard return / metadata
  • [[reentrancy]] — DN404 mirror callbacks

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.