Handle Native Tokens

View as Markdown

Understanding Native Tokens

Native tokens are the base currencies of their blockchains—for example, ETH on Ethereum, BNB on BNB Chain, and POL on Polygon. Because native tokens do not have contract addresses like ERC-20 tokens, the placeholder address: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE is commonly used to represent native tokens in blockchain transactions.

Standard Native Token Representation

For most of the EVM-compatible chains that we support, the native token is represented using the placeholder address 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE. This convention exists because native assets (e.g., ETH on Ethereum) do not have contract addresses like ERC-20 tokens.

Chain-Specific Exceptions

Two chains we support do not follow this convention:

  • Mantle uses a designated contract address for its native token, MNT.
  • Arc uses USDC as its native gas token, exposed through two interfaces that use different decimals.

Before integrating on either, read Chain-Specific Native Tokens.

Additional Resources

For more context on native token addresses:

Steps for Handling Standard Native Tokens

1

Skip the allowance check:

Unlike ERC-20 tokens, native tokens do not require an allowance or approval step. Therefore, you can skip the approve() call when preparing to send native tokens.

2

Set the transaction value:

Ensure that the value field in your transaction parameters accurately reflects the amount of native token (in wei) you intend to send.

See a full Swap API headless example that demonstrates how to handle native tokens.

Code example

Here’s a code snippet of how you can implement the above steps:

expandable
import { createWalletClient, http, parseEther, sendTransaction } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";
// Create a wallet client using your private key
const account = privateKeyToAccount("YOUR_PRIVATE_KEY");
const client = createWalletClient({
account,
chain: mainnet,
transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_KEY"), // Provide an authenticated RPC URL to avoid rate-limiting
});
// Check if the sellToken is a native token (ETH) to skip the allowance check
if (eth.address === "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE") {
console.log("Native token detected, no need for an allowance check");
} else {
// Check if allowance is required for non-native tokens
if (price.issues.allowance !== null) {
try {
const { request } = await eth.simulate.approve([
price.issues.allowance.spender,
maxUint256,
]);
// Remainder of code...
} catch (error) {
console.error("Error approving token:", error);
}
}
}
// Check if it's a native token (like ETH)
if (eth.address === "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE") {
const nonce = await client.getTransactionCount({
address: client.account.address,
});
// Directly sign and send the native token transaction
const txHash = await client.sendTransaction({
account: client.account,
chain: client.chain,
gas: quote?.transaction.gas ? BigInt(quote.transaction.gas) : undefined,
to: quote?.transaction.to,
data: quote.transaction.data,
value: BigInt(quote.transaction.value), // Ensure value is set for native tokens
gasPrice: quote?.transaction.gasPrice
? BigInt(quote.transaction.gasPrice)
: undefined,
nonce: nonce,
});
// Log the transaction hash
console.log("Transaction sent:", txHash);
}

Wrapping and Unwrapping between ETH and WETH

Easily wrap and unwrap between ETH and WETH by requesting a swap quote by setting sellToken and buyToken as either the contract address for WETH or ETH. The swap quote returned will provide the calldata to directly interact with the WETH9 contract and not with 0x Settler contract.

Wrap ETH

GET

curl --request GET \
https://api.0x.org/swap/allowance-holder/quote?buyToken=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&buyAmount=10000000" \
--header '0x-api-key: YOUR_API_KEY' \
--header '0x-version: v2'

Unwrap ETH

GET

curl --request GET \
https://api.0x.org/swap/allowance-holder/quote?buyToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sellToken=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&buyAmount=10000000" \
--header '0x-api-key: YOUR_API_KEY' \
--header '0x-version: v2'