Skip to main content

Token Approval Mechanism

Before executing any transaction that spends ERC20 tokens (swap, bridge, zap, etc.), a spender must be approved to access those tokens. The SDK provides multiple approval modes to handle different scenarios optimally. approve()’s mode param takes an ApprovalModes value (Default, PermitSingle, PermitWitnessTransferFrom, PermitBatchWitnessTransferFrom, AutoPermit). sign()’s permitType param takes a PermitTypes value — the same set, plus EIP2612Permit (which has no approve()/ApprovalModes counterpart, since EIP-2612 tokens never need an on-chain approval transaction). getAllowance() returns data keyed by token address, each entry { allowance: bigint, type: 'dzap' | 'permit2' | 'eip2612' }. There is no approvalNeeded/signatureNeeded field — derive those from allowance/type:

Approval Modes Deep Dive

1. Default Mode (Standard ERC20)

Traditional approval directly to the DZap contract.

2. Permit2 Modes

Uses Uniswap’s Permit2 for gas-efficient repeated approvals. There are three ApprovalModes/PermitTypes variants: PermitSingle (one token, standard permit), PermitWitnessTransferFrom (one token, witness-bound to the specific trade), and PermitBatchWitnessTransferFrom (multiple tokens in one signature).

3. EIP-2612 Permit Mode

Direct permit signatures to the DZap contract for supported tokens — no ApprovalModes/approve() call at all, only sign().
Automatically selects the optimal approval method: getAllowance({ mode: ApprovalModes.AutoPermit }) checks EIP-2612 support first (type: 'eip2612' in the response) and falls back to Permit2 (type: 'permit2') otherwise.

approvalTxnCallback

The approve() method accepts an optional approvalTxnCallback that is invoked for each approval transaction (viem WalletClient signers only; e.g. for logging or UI updates):
If the callback returns a TxnStatus other than success, remaining tokens in the batch are skipped.

Native token (skip approval)

For the native token (e.g. ETH), skip approval: the SDK’s native-token sentinel is 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE. getAllowance() already handles this internally (native tokens are returned with { allowance: maxUint256, type: 'dzap' } and never need an on-chain approval), but you can also filter them out yourself before calling approve:

Security Considerations

Limit Exposure

Use exact amounts for high-value or infrequent transactions

Monitor Allowances

Regularly audit and revoke unnecessary approvals

Use Permits When Possible

Permits reduce approval attack surface

Set Expiration Times

Use reasonable deadlines for permit signatures
Last modified on July 14, 2026