Hvorfor betale for en godkendelse, der i bund og grund blot er et digitalt nik? Hvis du nogensinde har siddet og ventet på, at din wallet først skulle “Approve” og derefter “Swap”, mens gasmåleren tikkede derudad, ved du præcis, hvor frustrerende det kan føles. De ekstra klik koster tid, penge – og for mange nye brugere: modet til overhovedet at prøve DeFi.
Den gode nyhed er, at EIP-2612 vender hele det billede på hovedet. Med ét enkelt pennestrøg – eller rettere: én digital signatur – kan du nu give dApps tilladelse til at flytte dine tokens helt uden at skulle fyre en separat on-chain-transaktion af. Resultatet? Gasfri godkendelser, færre trin i brugerrejsen og en mere strømlinet oplevelse, fra første klik til færdig handel.
I denne artikel dykker vi ned i, hvordan Permit-funktionen virker, hvorfor den er sikker, og hvad udviklere såvel som investorer bør vide, inden de hopper ombord. Vi ser også på konkrete use cases – fra én-klik swaps til meta-transaktioner – og kigger frem mod næste bølge af innovation med Uniswaps Permit2.
Er du klar til at spare på både nerver og gas? Læs videre, og opdag, hvordan EIP-2612 kan blive de smarte penge på din næste DeFi-rejse.
Baggrund: Traditionelle ERC-20-godkendelser og deres begrænsninger
ERC-20-standarden blev udformet med en simpel approve/allowance-model, der har tjent økosystemet godt siden 2017. Modellen fungerer i to trin:
- approve: Brugeren kalder
approve(spender, amount)på selve token-kontrakten og giver dermed spender (typisk en DEX eller DeFi-protokol) ret til at trække op til amount tokens fra brugerens konto. - transferFrom: Når handlingen (swap, deposit, låntagning osv.) skal udføres, kalder kontrakten
transferFrom(owner, spender, amount)og flytter tokens inden for det godkendte loft.
Hvorfor modellen giver friktion
| Udfordring | Praktisk konsekvens |
|---|---|
| Ekstra transaktion | Brugeren skal først sende approve og derefter selve handlingen – to on-chain hændelser i stedet for én. |
| Gasomkostninger | Approve koster typisk 40-60k gas oven i den efterfølgende handling. På høje gas-dage kan det være flere dollars pr. token. |
| Tidsforsinkelse | Brugeren må vente på, at godkendelsen bliver mined, før selve swap/deposit kan eksekveres. |
| Brugerforvirring | Nye brugere undrer sig over, hvorfor de skal “betale to gange” og signere to gange for én handling. |
Specifikt i dex- og defi-flows
- Hver ny token der handles, kræver separat approval. Mange brugere får derfor en hel “godkendelses-kø” første gang de prøver DeFi.
- Onboarding-flows, hvor man typisk vil bytte eller deponere tokens med det samme, ender i et stop-go-stop-go mønster, der koster konverteringer.
- Meta- og batch-transaktioner, som ellers kunne pakkes i ét klik, må opgive at inkludere token-overførsler, fordi godkendelsen skal ligge forud.
Sikkerheds-trade-offs
For at reducere friktionen vælger mange wallets og dApps at bede om uint256.max (“uendelig”) allowance, så brugeren kun behøver godkende én gang. Det skaber dog et permanent angrebsflade: bliver DEX-kontrakten opdateret med en bug, eller kompromitteres den, kan hele brugerens saldo drænes.
Opsummering
Approve/allowance-modellen er solid, men den koster både gas, tid og brugeroplevelse. For især førstegangs-brugere og mobile wallets er ekstra klik og ventetid en reel barriere. Dette sætter scenen for EIP-2612 Permit, der samler godkendelse og handling i én gasfri signatur.
Sådan virker Permit: Signaturer, nonces og EIP-712
Nøglen til EIP-2612 er, at godkendelsen flyttes fra en on-chain approve-transaktion til en off-chain signatur, som efterfølgende kan indløses af enhver på kæden. Det gøres via den nye funktion
function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
Funktionen accepterer tre grupper af data:
- Autorisering:
owner,spenderogvalue. - Replay-beskyttelse:
deadlineog en nonce, der ligger gemt i kontrakten. - Signaturen: de klassiske
v,r,s-felter fra Elliptic Curve Digital Signature Algorithm (ECDSA).
Eip-712: Maskinlæsbar signering
Signaturen dækker over en typed data-struktur defineret i EIP-712. For et ERC-20-token ser det typisk sådan ud:
Permit( address owner, address spender, uint256 value, uint256 nonce, uint256 deadline)
Walleten viser brugeren præcist de felter, der indgår, og danner signaturen over
keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, value, nonce, deadline ))
Den hash bliver dernæst kombineret med domæneseparatoren for at undgå identiske signaturer på tværs af kontrakter eller kæder:
| Felt | Formål |
|---|---|
name |
Token-navn (f.eks. “USD Coin”) |
version |
Kontraktversion (ofte “1”) |
chainId |
Undgår cross-chain misbrug efter en hardfork |
verifyingContract |
Selve token-adresssen |
Nonces & deadlines = ingen genspil
- Nonce: Et heltal, der kun kan bruges én gang pr.
owner. Kontrakten++nonce[owner]ved hver succesfuldpermit. - Deadline: UNIX-tid, hvorefter signaturen bliver ugyldig. Udviklere bør tillade 5-10 minutter som standard, ikke “uint(-1)”.
Denne kombination gør det umuligt for angribere at gensende en gammel signatur eller genbruge den på et andet netværk.
Hvem gør hvad?
- Bruger: Underskriver EIP-712-prompten i sin wallet – ingen gas betales her.
- dApp: Samler signaturen og kalder
permiton-chain, ofte i samme transaktion som den efterfølgende handling (swap, deposit …). - Relayer (valgfri): Kan betale gas for brugeren og videresende
permit+ handling, hvilket gør hele flowet fuldstændigt gasfrit for slutbrugeren.
Resultatet er, at dApp’en kan gå direkte videre til den egentlige forretning uden den sædvanlige “Approve token”-flaskehals – alt sammen sikret af kryptografisk verificerbare signaturer og robuste replay-værn.
Sikkerhed og risici: Bedste praksis for udviklere og brugere
Når godkendelser flyttes fra kæden til signaturer, skifter angrebsfladen karakter. Følg derfor disse grundregler, uanset om du er token-udvikler, dApp-bygger eller slutbruger:
- Begræns tidshorisonten
Sætdeadlinetil minutter – ikke dage. En kort udløbstid reducerer værdien af en kompromitteret signatur. - Undgå ubegrænsede allowances
Udfyldvaluemed det præcise beløb, der skal bruges, i stedet fortype(uint256).max. Det begrænser skaden, hvis spender-adressen kompromitteres. - Gennemsigtig UI
Wallets og dApps bør altid vise de fem nøglefelter –owner,spender,value,deadlineognonce– så brugeren forstår, hvad der signeres.
Tekniske faldgruber og hvordan de afværges
| Trussel | Beskrivelse | Afværgning |
|---|---|---|
| Signatur-malleabilitet | Ændring af s-værdien kan skabe en anden men gyldig signatur. |
Brug OpenZeppelin v4+ implementationer, som afviser ikke-kanoniske ECDSA-signaturer. |
chainId-skift |
Efter hard fork får kæden nyt ID; ældre signaturer kan blive ugyldige. | Inkludér altid aktuel chainId i domæneseparatoren og kræv ny signatur efter fork. |
| Phishing via off-chain prompts | Brugere lokkes til at “signere for at logge ind”, men afgiver reel permit. |
UI skal fremhæve spender-adressen (ofte en DEX-router). Educér brugere om aldrig at underskrive tilladelser, de ikke forventer. |
| Forældede allowances | Spender har fortsat ret efter brug, hvis allowance ikke nulstilles. | dApps bør kalde permit(..., value=0) efter handlingen, eller benytte transferFrom til at forbruge hele beløbet. |
Validér og log korrekt
dApp-side:
- Brug
_signTypedData/eth_signTypedData_v4til at indhente signaturen. - Verificér lokalt med
ethers.utils.verifyTypedDatafør du sender den on-chain. Så slipper brugeren for en mislykket transaktion, hvis signaturen er ugyldig. - Gem rå
v, r, si backend eller analytics-lag for revision og fejlsporing.
Wallet-side:
- List aktive
permit-allowances i UI, ligesom det allerede gøres for on-chainapprove. - Tilbyd “Revoke”-knap, der udfører en ny
permitmedvalue = 0eller kalder tokenetsapprove(0). - Marker signaturer, der nærmer sig udløb, så brugeren hurtigt kan forlænge eller slette dem.
Ekstra tip til udviklere
- Implementér
nonces()som public view returns (uint256) så front-ender kan hente den aktuelle nonce uden at parse events. - Supportér
permitselv på L2’s, hvor gasprisen er lav – det fjerner ét klikhop for brugeren. - Udgiv en
EIP-165interface-ID, så tredjeparts-dApps kan autodetektere, at din kontrakt understøtter EIP-2612.
Ved at kombinere korte deadlines, tydelig brugerflade og robust signatur-validering kan EIP-2612 nedsætte friktionen i DeFi uden at øge risikoen – men kun hvis både udviklere og brugere følger ovenstående retningslinjer.
Implementering og kompatibilitet i praksis
Den hurtigste vej til en kompatibel token er at nedarve fra ERC20Permit i OpenZeppelins kontrakt-bibliotek (v4.9+). Ét enkelt import-statement tilføjer hele EIP-2612-flowet – inkl. nonces(), DOMAIN_SEPARATOR() og selve permit().
// SPDX-License-Identifier: MITpragma solidity ^0.8.20;import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";contract USDK is ERC20Permit { constructor() ERC20("USD Københavner", "USDK") ERC20Permit("USD Københavner") // name field i domain separator { _mint(msg.sender, 1_000_000 ether); }}
Vigtige grænseflader (skal eksponeres, hvis du skriver kontrakten fra bunden):
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)function nonces(address owner) returns (uint256)function DOMAIN_SEPARATOR() returns (bytes32)
Bemærk, at OpenZeppelin automatisk håndterer EIP-712 domain separator, opdaterer nonces og validerer signaturernes v/r/s. Udvikleren skal primært beslutte chainId locking (standard i OZ), og hvorvidt deadline skal tjekkes mod block.timestamp (det gør OZ også).
2. Dapp-siden: Signér, send permit, udfør handling
- Hent nonce & byg typed data
const nonce = await token.nonces(userAddress);
Typed-data strukturen skal følge præcis skemaet i EIP-2612 (se tabel nedenfor). - Lad wallet signere
I ethers.js v6:// EIP-712 signaturconst sig = await signer.signTypedData( { name: "USD Københavner", version: "1", chainId: 1, verifyingContract: token.address, }, { Permit: [ { name:"owner", type:"address" }, { name:"spender", type:"address" }, { name:"value", type:"uint256" }, { name:"nonce", type:"uint256" }, { name:"deadline",type:"uint256" } ]}, { owner, spender, value, nonce, deadline });Underliggende RPC-metode er
eth_signTypedData_v4, som alle større wallets efterhånden understøtter. - Send on-chain
permit
De fleste dApp-flows læggerpermitførst i en multicall / batch:const tx = await router.swapExactTokensForETHSupportingFeeOnTransferTokens( value, 0, path, user, deadline, { permits: [{ ...sig, owner, spender: router.address, value, deadline }] });Fælles gas deles med den efterfølgende
swapellerdeposit, så brugeren stadig kun signer én gang.
| Field | Type | Formål |
|---|---|---|
| owner | address | Token-ejer, der signerer |
| spender | address | dApp / kontrakt, der får allowance |
| value | uint256 | Beløb (evt. type(uint256).max) |
| nonce | uint256 | Replay-beskyttelse |
| deadline | uint256 | Tidsgrænse for signaturen |
3. Wallet- og netværksstøtte
- Metamask, Rabby, Coinbase Wallet – fuld støtte til
eth_signTypedData_v4. - Hardware wallets – Ledger Live og Trezor Suite kan nu vise typed-data felter direkte; ældre firmware kræver blind signing.
- Layer 2 – Domain-separatoren indeholder
chainId; samme signatur kan ikke genbruges cross-chain, hvilket er en fordel på rollups.
4. Fallback-strategier, når et token ikke har eip-2612
dApp’en bør detektere permit() ved runtime:
const hasPermit = !!token.interface.getFunction("permit");
- Ingen permit
Vis standard Approve-skærm og forvent to transaktioner. Husk at estimere korrekt gas for traditionelle godkendelser. - Meta-transaktions fallback
Relayers kan betale gas og kaldeapprovepå vegne af brugeren, mod et lille gebyr i token’en selv (Gelato, Biconomy). Ikke helt gasfrit, men ét klik. - Uniswap Permit2
Hvis token ikke understøtter EIP-2612, men brugeren allerede har givet global Permit2-tilladelse, kan dApp’en udnytte det i stedet. Kræver dog support i routeren.
5. Test & verifikation
Unit-tests bør inkludere:
- Valid signatur = korrekt
noncestiger ogallowancesættes. - Forkert
v/r/seller udløbet deadline = revert. - Nonce-genbrug = revert (replay-angreb).
På dApp-siden kan man lave dry-run simulation via Anvil eller Tenderly for at sikre, at permit + den næste handling eksekveres i samme blok.
Med disse byggesten kan både token-udstedere og dApp-udviklere indføre brugeroplevelser, hvor “godkend” ikke længere er en flaskehals, men blot en usynlig del af flowet.
Use cases, måling af effekt og fremtiden (Permit2 m.m.)
Når udviklere først begynder at indarbejde permit-flowet, opdager de hurtigt, at værdien rækker langt ud over den umiddelbare gasbesparelse. Her er de mest udbredte anvendelser – og hvordan man kan måle, at de faktisk gør en forskel.
Praktiske use cases
- Én-klik swaps på DEX’er
Uden EIP-2612 skal brugeren:
1) sende en approve, vente på mined-status og
2) sende selve swap-kaldet.Med
permitsignerer brugeren blot off-chain, og dApp’en kalderpermit → swapi samme transaktion. Resultat: ét klik, én transaktion, lavere frafald. - Gasfri onboarding til wallets & DeFi-protokoller
Mange nye brugere har ingen native ETH/MATIC osv. at betale gas med. En relayer eller sponsoreret transaktion kan nøjes med at sende brugerens signatur on-chain og dække gasregningen. Dermed er første interaktion helt friktionsfri. - Batch- og meta-transaktioner
Wallets som Safe (tidl. Gnosis Safe) eller transaktionsbundlere (f.eks. Gelato, Biconomy) kan pakkepermitsammen med flere efterfølgende handlinger – f.eks. permit → deposit → stake – i én executeret transaktion. Det reducerer både block-tid og kompleksitet for brugeren.
Måling af effekt
| Metric | Før (approve+call) | Efter (permit) | Forbedring |
|---|---|---|---|
| Antal on-chain tx pr. handling | 2 | 1 | −50 % |
| Bruger-klik i UI | 2-3 | 1 | −60 – 70 % |
| Gasforbrug* (swap-eksempel) | ≈ 90 k | ≈ 60 k | −35 % |
| Konverteringsrate** | 67 % | 82 % | +15 pp |
*Gas afhænger af token-implementering og swap-router. **Konverteringsrate måles som fuldførte swaps i forhold til signerede intents.
Fremtiden: Uniswap permit2 m.m.
I november 2022 introducerede Uniswap Labs Permit2 – et udvidet godkendelseskoncept, der løser flere begrænsninger i EIP-2612:
| Funktion | EIP-2612 | Permit2 |
|---|---|---|
| Understøttede tokens | Kræver ændring af hver ERC-20-kontrakt | Én fælles kontrakt, token-agnostisk |
| Godkendelses-scope | Kun owner→spender |
Batch-godkendelser & sweeps |
| Revokering | approve(0) on-chain |
Central invalidate-funktion |
| Gas-omkostning | Lav til moderat | Endnu lavere via delt storage |
Permit2 gør det muligt for dApps at:
- Indhente én signatur, der dækker mange tokens og fremtidige transaktioner.
- Flytte tokens fra brugeren til flere kontrakter i samme call (sweep).
- Hurtigt tilbagekalde kompromitterede signaturer globalt.
Adoptionsudsigter
Flere større DEX’er (Uniswap v3/v4, 1inch), wallet-udbydere (Rainbow, Coinbase Wallet) og bundlere har allerede integreret EIP-2612, og flere byggesten som @openzeppelin/contracts gør det trivielt at tilføje til nye tokens. Permit2 er stadig tidlig, men forventes at vinde indpas, fordi den ikke kræver nye token-udrulninger. Kombinationen af EIP-2612 (token-niveau) og Permit2 (dApp-niveau) peger derfor mod en fremtid, hvor godkendelser sker én gang – og brugerne sjældent eller aldrig møder den famøse “Approve X”-popup igen.












