Skip to main content

EVM Token Allowance Checker

Updated on
Aug 07, 2026

Overview​

EVM-based blockchains see high usage of ERC-20 tokens, where users often grant spend allowances (via the Approval event).

In this Function example, we detect these approval logs and get valuable details related to the approval.

Sample Function​

Below is a Quicknode Function in JavaScript Node.js v20 runtime. It:

  1. Collects ERC-20 Approval logs (0x8c5be1e5…).
  2. Converts hex values to decimal.
  3. Groups logs by token address.
  4. Calls name() and symbol() on each token (using a minimal ABI).
  5. Appends tokenName and tokenSymbol to each approval record.
// If using CommonJS style in Node.js:
const { ethers } = require('ethers')

const HARDCODED_RPC_URL = 'https://my-eth-endpoint.quiknode.pro/SECRET/'

// The `Approval` event signature for ERC-20 tokens:
const APPROVAL_TOPIC =
'0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925'

// Minimal ERC-20 ABI (only name() and symbol())
const ERC20_ABI = [
'function name() view returns (string)',
'function symbol() view returns (string)',
]

/**
* Extract the last 40 hex characters from a padded address topic.
*/
function extractAddress(paddedAddress) {
if (typeof paddedAddress !== 'string' || paddedAddress.length < 40) {
console.error('Invalid address format:', paddedAddress)
return null
}
return '0x' + paddedAddress.slice(-40)
}

/**
* Convert a hex string to a decimal string, using BigInt.
*/
function hexToDecimal(hexValue) {
if (typeof hexValue !== 'string') {
console.error('Invalid hex value:', hexValue)
return '0'
}
hexValue = hexValue.replace(/^0x/, '')
if (hexValue === '') {
return '0'
}
try {
return BigInt('0x' + hexValue).toString()
} catch (error) {
console.error('Error converting hex to decimal:', error)
return '0'
}
}

/**
* Recursively locate Approval logs in the data structure.
* For each, store { token, owner, spender, amount, blockNumber, transactionHash }
*/
function findApprovalsInLogs(data, results) {
if (Array.isArray(data)) {
data.forEach(item => findApprovalsInLogs(item, results))
} else if (typeof data === 'object' && data !== null) {
if (data.topics && data.topics[0] === APPROVAL_TOPIC) {
const owner = extractAddress(data.topics[1])
const spender = extractAddress(data.topics[2])
const amount = hexToDecimal(data.data)
if (owner && spender) {
results.push({
token: data.address,
owner,
spender,
amount,
blockNumber: hexToDecimal(data.blockNumber),
transactionHash: data.transactionHash,
})
}
} else {
Object.values(data).forEach(val => findApprovalsInLogs(val, results))
}
}
}

/**
* fetchTokenInfo: calls name() and symbol() from ERC-20 contract.
*/
async function fetchTokenInfo(provider, tokenAddress) {
if (!ethers.isAddress(tokenAddress)) {
return { name: null, symbol: null }
}
const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider)
try {
const [name, symbol] = await Promise.all([
contract.name(),
contract.symbol(),
])
return { name, symbol }
} catch (err) {
console.error(`Error calling name()/symbol() on ${tokenAddress}`, err)
return { name: null, symbol: null }
}
}

/**
* main(params) - Quicknode Function entry point.
*
* We'll read logs from `params.data`, find approvals, fetch token name/symbol, and return a summary.
*/
async function main(params) {
console.log('DEBUG: Starting EVM token allowance checker (ethers v6.13.1)')

const logsData = params.data || []
let approvals = []
findApprovalsInLogs(logsData, approvals)

// Gather unique token addresses
const tokenAddresses = [...new Set(approvals.map(a => a.token.toLowerCase()))]

// Use ethers v6 with a hardcoded RPC provider
const provider = new ethers.JsonRpcProvider(HARDCODED_RPC_URL)

// For each token address, fetch name and symbol
let tokenInfoMap = {}
for (let addr of tokenAddresses) {
tokenInfoMap[addr] = await fetchTokenInfo(provider, addr)
}

// Attach name/symbol to each approval record
approvals.forEach(approval => {
const info = tokenInfoMap[approval.token.toLowerCase()] || {}
approval.tokenName = info.name
approval.tokenSymbol = info.symbol
})

const count = approvals.length
const message = `Found ${count} Approval events. Name/symbol fetched for ${tokenAddresses.length} tokens.`

return {
message,
approvals,
}
}

// Export for Quicknode Functions
module.exports = { main }

Replace 'https://my-eth-endpoint.quiknode.pro/SECRET/' on line 4 with your actual Ethereum mainnet RPC URL.

Request​

We will invoke the function with the following cURL command. A few notes:

  • Replace the YOUR_API_KEY with your own Quicknode API key - follow this guide for creating an API key.
  • Replace the FUNCTION_ID with the ID of your Function - you can find this in the URL when viewing your Function in the Quicknode Dashboard.
  • Use the block_number parameter to specify the block number you want to analyze. You can also omit this property for the function to run against the latest block.
curl -X POST "https://api.quicknode.com/functions/rest/v1/functions/FUNCTION_ID/call?result_only=true" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"network": "ethereum-mainnet",
"dataset": "logs"
}'

Response​

Resulting in the following response:

{
"message": "Found 26 Approval events. Fetched name/symbol for 21 unique tokens.",
"approvals": [
{
"token": "0x421b05cf5ce28cb7347e73e2278e84472f0e4a88",
"owner": "0xc57db940c5d56f8967914f19b2448a5b641f727d",
"spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"amount": "115792089237316195423570985008687907853269984665640564025466284007913129639935",
"blockNumber": "21514446",
"transactionHash": "0x60c47303d761d904ee735f504c151a9fb037063996ff369c160af4bb5712a7f9",
"tokenName": "Sentio Protocol",
"tokenSymbol": "SEN"
},
{
"token": "0x64c5cba9a1bfbd2a5faf601d91beff2dcac2c974",
"owner": "0x3fa6db082d42b47842ecf3e89ddc79473f5645f5",
"spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"amount": "115792089237316195423570985008687907853269984665583617695595542161914988347884",
"blockNumber": "21514446",
"transactionHash": "0xca2f1cd9b047c9b07118ce53fe0a8991808b912470a952396765711d76842fc8",
"tokenName": "Mystery",
"tokenSymbol": "MYSTERY"
},
{
"token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"owner": "0xd4bc53434c5e12cb41381a556c3c47e1a86e80e3",
"spender": "0x836951eb21f3df98273517b7249dceff270d34bf",
"amount": "26833530624",
"blockNumber": "21514446",
"transactionHash": "0xc254e19163e7bf5ec55c1d0d315ae5e675e3a6a127a9837547dc60dc4c1f15f3",
"tokenName": "USD Coin",
"tokenSymbol": "USDC"
},
{
"token": "0x26e550ac11b26f78a04489d5f20f24e3559f7dd9",
"owner": "0x0219957fafc72f937c6366855d0b7562cf5131bf",
"spender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"amount": "115792089237316195423570985008687907853269984665640564039457583747703391582002",
"blockNumber": "21514446",
"transactionHash": "0x57ed89700d6904370d3fc724f3cdf38b2a6e6c098072c366320fe0f8d30c3af3",
"tokenName": "Kekius Maximus",
"tokenSymbol": "KEKIUS"
},
{
"token": "0x6f965e544ee0be609b521aca47f16511595f0c53",
"owner": "0x4a1bee2e2d9417c3977b084f7b5eec5bac805897",
"spender": "0x80a64c6d7f12c47b7c66c5b4e20e72bc1fcd5d9e",
"amount": "115792089237316195423570985008687907853269984665640564039115768416052930243399",
"blockNumber": "21514446",
"transactionHash": "0xd63ecd08cc09e9a5eadff8d9a0c541921b379ca5db19443c22f559b5b66a7d1e",
"tokenName": "She-Dust",
"tokenSymbol": "SHEDUST"
},
{
"token": "0xae7ab96520de3a18e5e111b5eaab095312d7fe84",
"owner": "0xeb2d9f4f9a000eb173ce095369d3cb99d48a85b1",
"spender": "0xc92e8bdf79f0507f65a392b0ab4667716bfe0110",
"amount": "1022734223301193488",
"blockNumber": "21514446",
"transactionHash": "0x46ab83a9037631a8a595f58ae7522a20e3a728a27dd09c3650b13b79b9a875cf",
"tokenName": "Liquid staked Ether 2.0",
"tokenSymbol": "stETH"
},
{
"token": "0x8236a87084f8b84306f72007f36f2618a5634494",
"owner": "0xcca49c45f819912fd884b1725f4c9f669bfefbb0",
"spender": "0x34bdba9b3d8e3073eb4470cd4c031c2e39c32da8",
"amount": "307700",
"blockNumber": "21514446",
"transactionHash": "0xcdd563ad71307b516674f01defde99409550d41b08adcd4d232fa454172895a4",
"tokenName": "Lombard Staked Bitcoin",
"tokenSymbol": "LBTC"
},
{
"token": "0x9f52c8ecbee10e00d9faaac5ee9ba0ff6550f511",
"owner": "0xe83da89b0b4cdfd1c89cfb586eb3a92a9136b5ac",
"spender": "0xa2c1c1a473250094a6244f2bcf6cb51f670ad3ac",
"amount": "84000000000000000000",
"blockNumber": "21514446",
"transactionHash": "0x82e081b0b4b912394ee343d4d4164b6cb992a231ebb2e11fb1c7b0645c900b6d",
"tokenName": "Sipher Token",
"tokenSymbol": "SIPHER"
},
{
"token": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",
"owner": "0x37de6d5e26fd67f223dc992bf2dd400605f48c1b",
"spender": "0x881d40237659c251811cec9c364ef91dc08d300c",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0xe27e46db4a1feacc44606a95aba00f5a9e527aae25e9479b53f28739ca3200c5",
"tokenName": "Matic Token",
"tokenSymbol": "MATIC"
},
{
"token": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",
"owner": "0x37de6d5e26fd67f223dc992bf2dd400605f48c1b",
"spender": "0x881d40237659c251811cec9c364ef91dc08d300c",
"amount": "115792089237316195423570985008687907853269984665640564039156546390413129639935",
"blockNumber": "21514446",
"transactionHash": "0xb9fb983a2790ccaae756992ab1bd75a38fb205cc0c8e8997e9aa488000c78ef4",
"tokenName": "Matic Token",
"tokenSymbol": "MATIC"
},
{
"token": "0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0",
"owner": "0x74de5d4fcbf63e00296fd95d33236b9794016631",
"spender": "0xd82e10b9a4107939e55fcca9b53a9ede6cf2fc46",
"amount": "115792089237316195423570985008687907853269984665640558430868373315888675748634",
"blockNumber": "21514446",
"transactionHash": "0xb9fb983a2790ccaae756992ab1bd75a38fb205cc0c8e8997e9aa488000c78ef4",
"tokenName": "Matic Token",
"tokenSymbol": "MATIC"
},
{
"token": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"owner": "0x40bb7e10b2d03d68a6c275d189a544319b40e601",
"spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0xb5eede3dc185aeb5dba962c6fdd126656abe10ab261f0d2219570d208d4cb477",
"tokenName": "Wrapped Ether",
"tokenSymbol": "WETH"
},
{
"token": "0xf576e1f09e2eb4992d5ffdf68bec4ea489fa417d",
"owner": "0xf1c6b8ca186e389287353363792d77e095e73784",
"spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0xf2ae76be9e241ad790d4ed8f5320e1353621d96bf798ef11d7f4ac952a877dfe",
"tokenName": "ULTI",
"tokenSymbol": "ULTI"
},
{
"token": "0xde4ee8057785a7e8e800db58f9784845a5c2cbd6",
"owner": "0x974a28f1b216f8af3b5cf20693371049dbc0cefb",
"spender": "0x1111111254eeb25477b68fb85ed929f73a960582",
"amount": "5225482945056386753",
"blockNumber": "21514446",
"transactionHash": "0xcd9dd0b89d9e866cf3567eac4993904f6d1793d1e12a9e42532d800ef6f9e174",
"tokenName": "Dexe",
"tokenSymbol": "DEXE"
},
{
"token": "0xde4ee8057785a7e8e800db58f9784845a5c2cbd6",
"owner": "0x974a28f1b216f8af3b5cf20693371049dbc0cefb",
"spender": "0x1111111254eeb25477b68fb85ed929f73a960582",
"amount": "0",
"blockNumber": "21514446",
"transactionHash": "0xb50dd5eeefeda1de636cfbd6e46b4673e98c2acbb901eb631b42508d9f8bf11a",
"tokenName": "Dexe",
"tokenSymbol": "DEXE"
},
{
"token": "0x26e550ac11b26f78a04489d5f20f24e3559f7dd9",
"owner": "0x1262656546866f1b735f8e66b8626ee466ee6b2b",
"spender": "0xc92e8bdf79f0507f65a392b0ab4667716bfe0110",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0xd45b907e6e0a52fc701710b3626835be32224bf61bd98703259f6ffe8362d5f5",
"tokenName": "Kekius Maximus",
"tokenSymbol": "KEKIUS"
},
{
"token": "0x8ccd897ca6160ed76755383b201c1948394328c7",
"owner": "0x203d472155ce4e27b7a50117cc1008bf18aa6dff",
"spender": "0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae",
"amount": "390395764140",
"blockNumber": "21514446",
"transactionHash": "0xcf541a8388d9793432e58581d4899ebd86c19dbe0a8844afd296381d933c9ee6",
"tokenName": "Wrapped Balance AI",
"tokenSymbol": "wBAI"
},
{
"token": "0xbbcbf4dd68df01ad1aa1c568ca7a6c02787aa494",
"owner": "0x264533bd62512a9e7e791236625adbdf3e8377f3",
"spender": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"amount": "31960202801638",
"blockNumber": "21514446",
"transactionHash": "0xfab92da4963285b3416540e22aaa0b8a4a42ffb202cd42070d4445d965141ae3",
"tokenName": "Snax Inu",
"tokenSymbol": "Snax"
},
{
"token": "0xfd4ca4a692f14d88af3e7ae13cf00d5095213b25",
"owner": "0x5daef2e38b446920a5bc2d16a3d33aa36d271da9",
"spender": "0x0000000000001ff3684f28c67538d4d072c22734",
"amount": "733365430426900063231560",
"blockNumber": "21514446",
"transactionHash": "0x64ca739964884af4f3a2368042564a9b4c69b8277e19b12319c0c6209da24d4a",
"tokenName": "Wiskers",
"tokenSymbol": "WSKR"
},
{
"token": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"owner": "0x2aca0c7ed4d5eb4a2116a3bc060a2f264a343357",
"spender": "0x8f88ae3798e8ff3d0e0de7465a0863c9bbb577f0",
"amount": "60000000000000000",
"blockNumber": "21514446",
"transactionHash": "0xce8a81a82f91086b5a035a7245c6e2c0bfe43159cb0dbb40e483a7e86e3312b3",
"tokenName": "Wrapped Ether",
"tokenSymbol": "WETH"
},
{
"token": "0x29d5cabc57870e9a27a655594bcd08152d0a135b",
"owner": "0x44887642ddee3a01a8c89522e2262603841c67db",
"spender": "0x40aa958dd87fc8305b97f2ba922cddca374bcd7f",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0x20b6f2542fe9e0f43546359cf59cde36e52298819a6ef1270b4edcd2ad33b284",
"tokenName": "The Surge",
"tokenSymbol": "SURGE"
},
{
"token": "0x5d31692f98696897cb85d0188e99d484d597fe01",
"owner": "0x282b3538621091508461ecc98eaf47af14915296",
"spender": "0x40aa958dd87fc8305b97f2ba922cddca374bcd7f",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0x2cc71dd3845b8246ced63bc08c40cee02d80b8e4a1a4d7bbe7433a633ceafc21",
"tokenName": "Bye to cash",
"tokenSymbol": "BTC"
},
{
"token": "0x2a2550e0a75acec6d811ae3930732f7f3ad67588",
"owner": "0x8f228609eb5ee750efb00e92611aa96582decadc",
"spender": "0x40aa958dd87fc8305b97f2ba922cddca374bcd7f",
"amount": "2888983660164051964987868",
"blockNumber": "21514446",
"transactionHash": "0x17f6f00fe411bb7631af1c5be05ed90705dfe8b81b9ec68a2b9406abc81251f7",
"tokenName": "PathDao",
"tokenSymbol": "PATH"
},
{
"token": "0x20cd2e7ec8f5d8b337fe46a4f565ccef1561b9a9",
"owner": "0x4e9c34c34e9d00966648d20d2da58d07377465fc",
"spender": "0x33d933cdb77be8469c113b4c8162473b72430cc2",
"amount": "10000000000000000000000000",
"blockNumber": "21514446",
"transactionHash": "0xd25d648f5783ace261ba18260ed479771adfd7676123f9da396d8ca65cab7fe7",
"tokenName": "ESG",
"tokenSymbol": "ESG"
},
{
"token": "0x332a8ee60edff0a11cf3994b1b846bbc27d3dcd6",
"owner": "0x5e2787b3aa6ec78278df6291a5d486ff0b20c9de",
"spender": "0x888888888889758f76e7103c6cbf23abbf58f946",
"amount": "95060",
"blockNumber": "21514446",
"transactionHash": "0x36985a3aed029ef5cfc48371efdc8c48917ba314b4a98abad962af79e56da89c",
"tokenName": "PT Corn Lombard LBTC 26DEC2024",
"tokenSymbol": "PT-cornLBTC-26DEC2024"
},
{
"token": "0x0f48e776a4d983c0dddf4c0c946d66e3786f134f",
"owner": "0xccb75c1880e9d37dce0a24c633352cc1ec1a8e4d",
"spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"blockNumber": "21514446",
"transactionHash": "0xc9ab8551e0761b5a0384d7b61d9cdb6648c43f9643503e2cec3c22a5881828be",
"tokenName": "XETRA AI",
"tokenSymbol": "XETRA"
}
]
}

Learn more about Quicknode Functions.