Skip to main content
Before signing, check whether the quote response includes a tokenRequirements field. This is only relevant for EOA users — smart accounts handle approvals automatically via preclaim ops.

Smart accounts

No action required. The Orchestrator handles token approvals internally using preclaim ops on the smart account.

EOAs

If tokenRequirements is present in the quote response, the user must complete these steps before signing. There are two types:
  • approval: approve the specified token to the Permit2 contract on the specified chain.
  • wrap: wrap native ETH into WETH on the specified chain (required when ETH is the source token).
{
  "8453": {
    "0x0000000000000000000000000000000000000000": {
      "type": "wrap",
      "amount": "102656447694688542"
    },
    "0x4200000000000000000000000000000000000006": {
      "type": "approval",
      "amount": "102656447694688542",
      "spender": "0x000000000022d473030f116ddee9f6b43ac78ba3"
    }
  }
}
In this example, the user must first wrap ETH on Base, then approve WETH to Permit2.

ETH wrapping

import { switchChain, writeContract } from "@wagmi/core";

await switchChain(wagmiConfig, { chainId: Number(chainId) });

await writeContract(wagmiConfig, {
  address: "0x4200000000000000000000000000000000000006", // WETH on the chain
  abi: [
    {
      name: "deposit",
      type: "function",
      stateMutability: "payable",
      inputs: [],
      outputs: [],
    },
  ],
  functionName: "deposit",
  value: BigInt(requirement.amount),
});

ERC-20 approvals

Approve to the Permit2 contract. We recommend using maxUint256 to avoid repeated approval prompts on future intents:
import { switchChain, writeContract } from "@wagmi/core";
import { maxUint256, erc20Abi } from "viem";

await switchChain(wagmiConfig, { chainId: Number(chainId) });

await writeContract(wagmiConfig, {
  address: tokenAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [requirement.spender, maxUint256],
});
Approvals are always to Permit2 — one of the most widely deployed and audited contracts in the ecosystem. Setting max approval here does not grant Rhinestone any direct access to your funds.
If you prefer exact approvals, inspect the tokensSpent field in the quote response. This shows the exact amount that will be used, so approving that amount will be sufficient:
// Use tokensSpent amount instead of maxUint256 for exact approvals
const chainSpend = intentCost.tokensSpent[chainId];
const tokenAmount = chainSpend[tokenAddress]?.unlocked;

await writeContract(wagmiConfig, {
  address: tokenAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [requirement.spender, BigInt(tokenAmount)],
});

Next steps

Signing the intent

Sign each element of the intent with EIP-712.