LayerHopdocs

Concepts

Approvals

When an EVM transaction comes with an ERC-20 approval, what it means and how to send it safely.

Open in ClaudeOpen in ChatGPT

When you get one#

Selling an ERC-20 token (USDC, USDT…) on an EVM chain requires the provider's contract to pull the tokens from the user's wallet. That needs an ERC-20 allowance. When it does, POST /v1/orders returns the transaction with an approval:

JSON
{
  "vm": "evm",
  "chainId": 8453,
  "to": "0xa5F5…9934",
  "data": "0x58109c…",
  "value": "0",
  "approval": {
    "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "spender": "0xa5F5…9934",
    "amount": "100000000"
  }
}

Selling the native coin (ETH, BNB, POL) never needs an approval; the amount travels in value instead. Solana transactions never carry an approval.

How to handle it#

  1. Read the current allowance: allowance(owner = user, spender) on approval.token.
  2. If it is less than approval.amount, send approve(spender, amount) from the user's wallet and wait for it to be mined.
  3. Then send the main transaction (to, data, value).
TypeScript
if (tx.vm === "evm" && tx.approval) {
  const { token, spender, amount } = tx.approval;
  const current = await pub.readContract({ address: token, abi: erc20Abi, functionName: "allowance", args: [user, spender] });
  if (current < BigInt(amount)) {
    const hash = await wallet.writeContract({ address: token, abi: erc20Abi, functionName: "approve", args: [spender, BigInt(amount)] });
    await pub.waitForTransactionReceipt({ hash });
  }
}

Good practice#

  • Approve the exact amount. LayerHop returns the exact input amount; avoid unlimited approvals unless the user opts in.
  • Spender is not always to. For 0x the spender is the AllowanceHolder contract, while to is the settlement contract. Always use approval.spender.
  • USDT on Ethereum rejects changing a non-zero allowance to another non-zero value. If the current allowance is non-zero but too small, approve 0 first, then the new amount.
  • The quote clock keeps running while the approval confirms. If the approval took long, the main transaction may fail to build or execute; re-quote if expiresAt has passed.

Coming soon

Permit2 / EIP-2612 signatures to skip the separate approval transaction where providers support it.