원클릭으로
permit2-allowance-flow
Complete approval flow with reset-to-zero pattern. Use when implementing full ERC20 and Permit2 approval workflow.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Complete approval flow with reset-to-zero pattern. Use when implementing full ERC20 and Permit2 approval workflow.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
AI-powered crypto trading agent, wallet API, and LLM gateway via natural language. Use when the user wants to trade crypto, trade tokenized stocks and ETFs (spot or leveraged), check portfolio balances (with PnL and NFTs), view token prices, search tokens, transfer crypto, manage NFTs, use leverage (Hyperliquid or Avantis), bet on Polymarket, deploy tokens, set up automated trading, sign and submit raw transactions, call or deploy x402 paid API endpoints, browse the web, or access LLM models through the Bankr LLM gateway funded by your Bankr wallet. Supports Base, Ethereum, Polygon, Solana, Unichain, World Chain, Arbitrum, BNB Chain, and Robinhood Chain.
Live pay-per-call data for crypto and DeFi protocol risk, funding rates, open interest, liquidations, stablecoin health, macro, equities, and on-chain intelligence — settled per query in USDC on Base via x402, no signup or API key.
This skill should be used when the user asks about "create3", "deploy", "diamond factory", "package", "deterministic deployment", "cross-chain", "DiamondPackageCallBackFactory", "FactoryService", or needs guidance on deploying Diamond proxies and facets using Crane's factory system.
This skill should be used when the user asks about "testbase", "behavior library", "invariant test", "handler", "fuzz test", "test pattern", "Behavior_", "TestBase_", "mock", "vm.mockCall", "unit test", "write a test", "CraneTest", or needs guidance on Crane's testing infrastructure for writing comprehensive smart contract tests. Prefer production code over mocks.
Foundry cheatcodes, assertions, and forge test CLI. Use for vm.prank, expectRevert, verbosity, and general Foundry mechanics. For Crane/IndexedEx protocol and Diamond tests, prefer crane-testing and production-first deploy paths over mocks.
This skill should be used when the user asks about "facet", "target", "repo", "diamond pattern", "storage slot", "guard function", "DFPkg", "AwareRepo", "Service pattern", "Modifiers", "ERC2535", or needs guidance on Crane's core architectural patterns for building modular, upgradeable smart contracts.
| name | permit2-allowance-flow |
| description | Complete approval flow with reset-to-zero pattern. Use when implementing full ERC20 and Permit2 approval workflow. |
Full implementation with reset-to-zero pattern for tokens that require it.
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
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 })
}
}