Handles secure ERC20/Permit2 allowance workflows, including reset-to-zero logic.
Install
mkdir -p .claude/skills/permit2-allowance-flow && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14459" && unzip -o skill.zip -d .claude/skills/permit2-allowance-flow && rm skill.zipInstalls to .claude/skills/permit2-allowance-flow
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Complete approval flow with reset-to-zero pattern. Use when implementing full ERC20 and Permit2 approval workflow.Key capabilities
- →Ensure ERC20 allowance for Permit2.
- →Handle reset-to-zero pattern for tokens requiring it.
- →Ensure Permit2 allowance for a specific spender.
- →Write contract transactions for approval.
- →Wait for transaction receipts.
How it works
This skill ensures spending limits by checking current ERC20 and Permit2 allowances, and if insufficient, it executes approval transactions, including a reset-to-zero pattern for specific tokens, and waits for transaction receipts.
Inputs & outputs
When to use permit2-allowance-flow
- →Implement token approvals
- →Manage Permit2 allowances
- →Handle ERC20 transfer flows
About this skill
Permit2 Allowance Transfer - Complete Flow
Full implementation with reset-to-zero pattern for tokens that require it.
Constants
const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'
const PERMIT2_APPROVE_ABI = [
{
inputs: [
{ name: 'token', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint160' },
{ name: 'expiration', type: 'uint48' }
],
name: 'approve',
outputs: [],
stateMutability: 'nonpayable',
type: 'function'
}
] as const
Complete Approval Function
async function ensureSpendingLimits(
tokenAddress: string,
spenderAddress: string,
amountNeeded: bigint,
writeContractAsync: (config: WriteContractParameters) => Promise<Hash>,
publicClient: PublicClient,
address: string
) {
// Step 1: Ensure ERC20 → Permit2 allowance
const currentErc20Allowance = await publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'allowance',
args: [address, PERMIT2_ADDRESS]
})
if (currentErc20Allowance < amountNeeded) {
// Some tokens (like USDT) require resetting to 0 first
try {
const hash = await writeContractAsync({
address: tokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [PERMIT2_ADDRESS, amountNeeded]
})
await publicClient.waitForTransactionReceipt({ hash })
} catch {
// Reset to 0, then approve
const hash0 = await writeContractAsync({
address: tokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [PERMIT2_ADDRESS, 0n]
})
await publicClient.waitForTransactionReceipt({ hash: hash0 })
const hash1 = await writeContractAsync({
address: tokenAddress,
abi: erc20Abi,
functionName: 'approve',
args: [PERMIT2_ADDRESS, amountNeeded]
})
await publicClient.waitForTransactionReceipt({ hash: hash1 })
}
}
// Step 2: Ensure Permit2 → Spender allowance
const currentPermit2Allowance = await publicClient.readContract({
address: PERMIT2_ADDRESS,
abi: [{
inputs: [
{ name: 'owner', type: 'address' },
{ name: 'token', type: 'address' },
{ name: 'spender', type: 'address' }
],
name: 'allowance',
outputs: [
{ name: 'amount', type: 'uint160' },
{ name: 'expiration', type: 'uint48' },
{ name: 'nonce', type: 'uint48' }
],
stateMutability: 'view',
type: 'function'
}],
functionName: 'allowance',
args: [address, tokenAddress, spenderAddress]
})
if (currentPermit2Allowance[0] < amountNeeded) {
const threeDaysSecs = 3n * 24n * 60n * 60n
const expiration = BigInt(Math.floor(Date.now() / 1000)) + threeDaysSecs
const hash = await writeContractAsync({
address: PERMIT2_ADDRESS,
abi: PERMIT2_APPROVE_ABI,
functionName: 'approve',
args: [tokenAddress, spenderAddress, amountNeeded, expiration]
})
await publicClient.waitForTransactionReceipt({ hash })
}
}
When not to use it
- →When the user needs to implement a custom approval flow without the reset-to-zero pattern.
- →When the user wants to bypass the Permit2 allowance mechanism.
- →When the user needs to manage tokens that do not require a reset-to-zero pattern.
Limitations
- →The skill specifically implements the reset-to-zero pattern for ERC20 tokens.
- →It relies on the `PERMIT2_ADDRESS` constant.
- →It sets a fixed expiration of three days for Permit2 allowances.
How it compares
This skill provides a complete and reliable approval flow for ERC20 and Permit2 tokens, including a specific reset-to-zero pattern for problematic tokens, which is more complete than a basic approval transaction.
Compared to similar skills
permit2-allowance-flow side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| permit2-allowance-flow (this skill) | 0 | 4mo | No flags | Advanced |
| tier-entitlements | 1 | 6mo | No flags | Intermediate |
| qruiq-google-auth | 0 | 4mo | Review | Intermediate |
| dev-supabase | 0 | 2mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
tier-entitlements
dadbodgeoff
Implement subscription tier-based feature gating and usage limits. Centralized tier configuration, database usage tracking, and clean APIs for checking limits.
qruiq-google-auth
qruiqai
|
dev-supabase
aibot88
Backend development with Supabase. Trigger when the user wants to configure auth, the database, or Supabase storage.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
fastapi-pro
sickn33
Build high-performance async APIs with FastAPI, SQLAlchemy 2.0, and Pydantic V2. Master microservices, WebSockets, and modern Python async patterns. Use PROACTIVELY for FastAPI development, async optimization, or API architecture.
drizzle-orm
EpicenterHQ
Drizzle ORM patterns for type branding and custom types. Use when working with Drizzle column definitions, branded types, or custom type conversions.