What is EIP-2612 on Solana?


EIP-2612 是 ERC-20 许可扩展,允许代币持有者通过链下签名而非链上批准交易,向智能合约或其他账户授予支出额度。通过在单个 permit() 调用中嵌入签名数据,用户可以节省 gas 费用,集成方也可以将批准和操作捆绑到一个原子交易中。

Key Characteristics

  • Gasless, single-call approvals: 持有者签署一条链下 EIP-712 消息,一次 permit() 调用即可在验证签名的同时立即设置额度,无需单独的链上批准,从而简化用户体验。
  • Security & backward compatibility: Each permit consumes a unique, ever-increasing nonce and the signature is bound to the token's EIP-712 domain (name, chain ID, contract address). The extension adds < 200 bytes to a standard ERC-20, leaving balances and transfers untouched.
  • Seamless DeFi & wallet integration: DEXs, lending protocols, routers, and meta-TX relayers can batch permit -> action in one atomic transaction, while wallets like MetaMask and Ledger present it as a familiar Sign Message flow instead of a gas-priced approval.

Why EIP-2612 Is Unnecessary on Solana

Since Solana lets you combine approval and action in one atomic transaction and allows someone else to cover the fees by default, the two pain points that EIP-2612 solves on Ethereum (duplicated approvals and user-paid gas) are already removed at the protocol level. There is no need for an additional permit function, typed-data domain, or contract upgrade; the standard SPL-Token program satisfies those requirements out of the box.

Token Approval Model

On Ethereum, transferring ERC20 tokens between two addresses often requires approve + transferFrom if you're doing it on behalf of a user. On Solana, each user already has an ATA (Associated Token Accounts) recognized by the Token Program. A single Solana transaction can atomically call multiple instructions, so no separate approval step is required. You can directly transfer from one user's token account to another in one go.

Fee-Payer (Gas Delegation) Model

Every Solana transaction explicitly names both its signers and a fee-payer. A user can sign the transaction while designating a third party (a wallet service, dApp backend, or relayer) to pay the fees. The protocol therefore delivers the same gasless user experience that EIP-2612 targets, but without introducing a special off-chain signature scheme such as EIP-712.

How to do EIP-2612 on Solana

Below are two minimal, copy-paste-ready examples that map the two most common permit -> action scenarios to Solana's native primitives. Both use @solana/web3.js and @solana/spl-token.

1. Owner Pays the Fee (Self-Sponsored Transfer)

The owner both signs and pays the fee. All we do is bundle Approve -> Transfer into a single atomic transaction, no extra permit function required.

javascript
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import {
  createApproveInstruction,
  createTransferInstruction,
  getAssociatedTokenAddressSync
} from "@solana/spl-token";

const connection = new Connection("https://api.devnet.solana.com");
const owner = Keypair.generate();
const delegate = owner.publicKey;
const recipient = new PublicKey("DESTINATION_WALLET");
const mint = new PublicKey("TOKEN_MINT");
const amount = 1_000_000;

const ownerATA = getAssociatedTokenAddressSync(mint, owner.publicKey);
const recipientATA = getAssociatedTokenAddressSync(mint, recipient);

const ixApprove = createApproveInstruction(ownerATA, delegate, owner.publicKey, amount);
const ixTransfer = createTransferInstruction(ownerATA, recipientATA, owner.publicKey, amount);

const tx = new Transaction().add(ixApprove, ixTransfer);
tx.feePayer = owner.publicKey;
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;

tx.sign(owner);
const sig = await connection.sendRawTransaction(tx.serialize());
console.log("Sent (self-sponsored):", sig);

2. Third Party Pays the Fee (Relayed Transfer)

Here the holder signs the instruction, but a relayer (or dApp back-end) covers the SOL fee. Solana supports this natively via the feePayer field plus partial signatures.

javascript
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import { createTransferInstruction, getAssociatedTokenAddressSync } from "@solana/spl-token";

const connection = new Connection("https://api.devnet.solana.com");
const owner     = Keypair.generate();          // replace with real keypair
const feePayer  = Keypair.generate();          // replace with real keypair
const recipient = new PublicKey("DESTINATION_WALLET");
const mint      = new PublicKey("TOKEN_MINT");
const amount    = 500_000;

const ownerATA     = getAssociatedTokenAddressSync(mint, owner.publicKey);
const recipientATA = getAssociatedTokenAddressSync(mint, recipient);

const ix = createTransferInstruction(ownerATA, recipientATA, owner.publicKey, amount);

const tx = new Transaction().add(ix);
tx.feePayer        = feePayer.publicKey;
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;

tx.partialSign(owner);
tx.sign(feePayer);

const sig = await connection.sendRawTransaction(tx.serialize());
console.log("Sent (relayer-sponsored):", sig);
EVM TO SVM

Start building on Solana

Node storing all data and participating in consensus

  • Ethereum: Archive Node
  • Solana: [n/a]

Node storing some data and participating in consensus

  • Ethereum: Full Node
  • Solana: Consensus Node

Node storing some data and not participating in consensus

  • Ethereum: Light Node
  • Solana: RPC Node

Node storing all data and participating in consensus

  • Ethereum: Archive Node
  • Solana: [n/a]

Node storing some data and participating in consensus

  • Ethereum: Full Node
  • Solana: Consensus Node

Node storing some data and not participating in consensus

  • Ethereum: Light Node
  • Solana: RPC Node

管理者

©️ 2026 Solana 基金会版权所有
取得联系
What is EIP-2612 on Solana? | Solana