Skip to main content
Common errors when integrating with your custom stablecoin and how to resolve them.

Common errors

AddressBlocklisted

Error: Transaction reverts with AddressBlocklisted(address)Solution: The sender, recipient, or caller address is on the blocklist. Use isBlocklisted(address) to check status before sending. If you believe this is an error, contact Coinbase support.
const isBlocked = await token.isBlocklisted(walletAddress);
if (isBlocked) {
  throw new Error("Address is blocked from transfers");
}

EnforcedPause

Error: Transaction reverts with EnforcedPause()Solution: All transfers on this stablecoin are currently paused. Monitor the Unpaused event to detect when transfers resume. Do not retry until the contract is unpaused.
// Listen for the Unpaused event
token.once("Unpaused", () => {
  console.log("Transfers resumed");
});

ERC20InsufficientBalance

Error: Transaction reverts with ERC20InsufficientBalanceSolution: The sender does not have enough tokens. Check the balance before sending:
const balance = await token.balanceOf(signer.address);
if (balance < amount) {
  throw new Error(`Insufficient balance: have ${balance}, need ${amount}`);
}

ERC20InsufficientAllowance

Error: Transaction reverts with ERC20InsufficientAllowanceSolution: The caller’s spending allowance is insufficient for transferFrom. Call approve on the token contract first:
const allowance = await token.allowance(ownerAddress, spenderAddress);
if (allowance < amount) {
  await token.approve(spenderAddress, amount);
}

ERC2612ExpiredSignature

Error: permit call reverts with ERC2612ExpiredSignatureSolution: The permit deadline has passed. Generate a new signature with a future deadline:
const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now

ERC2612InvalidSigner

Error: permit call reverts with ERC2612InvalidSignerSolution: The signature does not match the owner address, or the nonce is stale. Ensure you are:
  1. Signing with the correct wallet (the token owner)
  2. Reading the current nonce with nonces(owner) immediately before signing
  3. Using the correct verifyingContract (the token address, not the spender)
  4. Setting the EIP-712 domain name to the exact value returned by token.name() and version to "1" — a mismatch in either field produces an invalid signature
The same domain rules apply to ERC-3009 transferWithAuthorization signatures.

AuthorizationAlreadyUsed

Error: ERC-3009 call reverts with AuthorizationAlreadyUsed(authorizer, nonce)Solution: The nonce has already been consumed or canceled. Generate a new random nonce for each authorization:
const nonce = ethers.hexlify(ethers.randomBytes(32));
Check whether a nonce has been used before submitting:
const used = await token.authorizationState(fromAddress, nonce);
if (used) throw new Error("Authorization nonce already used");

AuthorizationExpired

Error: ERC-3009 call reverts with AuthorizationExpired(validBefore)Solution: The authorization’s validBefore timestamp has passed. Have the token holder sign a new authorization with a future validBefore.

AuthorizationNotYetValid

Error: ERC-3009 call reverts with AuthorizationNotYetValid(validAfter)Solution: The authorization cannot be submitted yet. Either wait until after validAfter, or set validAfter to 0 for authorizations that should be valid immediately.

CallerMustBePayee

Error: receiveWithAuthorization reverts with CallerMustBePayee(caller, payee)Solution: receiveWithAuthorization can only be submitted by the to address. Ensure the transaction is signed and sent by the intended recipient, or use transferWithAuthorization if any relayer should be able to submit.

Insufficient gas

Error: Transaction fails with insufficient funds for gasSolution: You need Base Sepolia ETH for gas. Get testnet ETH from CDP Faucet.

Production Readiness

Best practices for production integrations

Examples

Code samples for common scenarios

Reference

Full function and program reference

Quickstart

Back to quickstart