@@ -44,6 +44,7 @@ Older tokens such as USDT predate EIP-2612, so they expose custom meta-transacti
4444## EIP-2612 Permit vs Meta-Transaction
4545
4646### USDT Meta-Transaction (Gasless USDT Lesson)
47+
4748``` js
4849// Salt-based domain separator
4950const domain = {
@@ -63,6 +64,7 @@ const types = {
6364```
6465
6566### USDC Permit (This Lesson)
67+
6668``` js
6769// Version-based domain separator (EIP-2612 standard)
6870const domain = {
@@ -87,14 +89,14 @@ const types = {
8789
8890## Key Differences
8991
90- | Aspect | USDT Meta-Transaction (Gasless USDT Lesson) | USDC Permit (This Lesson) |
91- | --------| ---------------------------------| ---------------------------|
92- | ** Standardization** | Custom, tether-specific | Formalized in EIP-2612 |
93- | ** Domain separator** | Uses ` salt ` derived from chain | Uses ` version ` plus ` chainId ` |
94- | ** Typed struct** | ` MetaTransaction ` with encoded bytes | ` Permit ` with discrete fields |
95- | ** Expiry control** | No expiration | Explicit ` deadline ` |
96- | ** Transfer helper** | ` transferWithApproval ` | ` transferWithPermit ` |
97- | ** Method selector** | ` 0x8d89149b ` | ` 0x36efd16f ` |
92+ | Aspect | USDT Meta-Transaction (Gasless USDT Lesson) | USDC Permit (This Lesson) |
93+ | -------------------- | ------------------------------------------- | ----------------------------- |
94+ | ** Standardization** | Custom, tether-specific | Formalized in EIP-2612 |
95+ | ** Domain separator** | Uses ` salt ` derived from chain | Uses ` version ` plus ` chainId ` |
96+ | ** Typed struct** | ` MetaTransaction ` with encoded bytes | ` Permit ` with discrete fields |
97+ | ** Expiry control** | No expiration | Explicit ` deadline ` |
98+ | ** Transfer helper** | ` transferWithApproval ` | ` transferWithPermit ` |
99+ | ** Method selector** | ` 0x8d89149b ` | ` 0x36efd16f ` |
98100
99101Keep this table nearby while refactoring; you will touch each of these rows as you migrate the code.
100102
@@ -173,14 +175,14 @@ const transferContract = new ethers.Contract(
173175)
174176
175177const transferCalldata = transferContract .interface .encodeFunctionData (' transferWithPermit' , [
176- USDC_ADDRESS , // token
177- transferAmount, // amount
178- RECEIVER_ADDRESS , // target
179- feeAmount, // fee
180- deadline, // deadline ⚠️ New parameter
181- r, // sigR
182- s, // sigS
183- v, // sigV
178+ USDC_ADDRESS , // token
179+ transferAmount, // amount
180+ RECEIVER_ADDRESS , // target
181+ feeAmount, // fee
182+ deadline, // deadline ⚠️ New parameter
183+ r, // sigR
184+ s, // sigS
185+ v, // sigV
184186])
185187```
186188
@@ -243,11 +245,13 @@ const TRANSFER_ABI = [
243245## Why Two Approval Methods?
244246
245247** USDT** (pre-EIP-2612 era):
248+
246249- Custom meta-transaction implementation
247250- Salt-based domain separator
248251- Encodes full function call in signature
249252
250253** USDC** (EIP-2612 compliant):
254+
251255- Standardized permit interface
252256- Version + chainId domain separator
253257- Simpler parameter structure
0 commit comments