How the Gauntlet SDK tracks on-chain volume back to your integration using ERC-8021 builder codes, and how to monitor attributed activity.
Attribution links on-chain deposit and withdrawal volume back to your integration — enabling fee sharing and volume reporting in the Developer Portal. The SDK embeds attribution automatically on every transaction it builds.
You must request a builder code from Gauntlet — it is not self-serve. Request one as part of your partnership onboarding. The Gauntlet indexer must recognize your specific code for volume to be counted against your integration; using an arbitrary string will append bytes to calldata but attribution will not be tracked.Your builder code is separate from your API key — you may receive them together or at different stages of onboarding.Once you have it, set builderCode on GauntletClient:
import { GauntletClient, AttributionMode } from '@gauntlet-xyz/sdk'const client = new GauntletClient({ evmClients: { ... }, wallet: walletClient, builderCode: 'your-builder-code', // issued by Gauntlet — request from the partnerships team attributionMode: AttributionMode.PUBLIC, // default — no need to set explicitly})
Without builderCode, AttributionMode.PUBLIC appends nothing and transactions are unattributed.
The SDK encodes attribution as an ERC-8021 calldata suffix appended to every transaction. It does not affect contract execution — the Gauntlet indexer reads it to attribute the volume.ERC-8021 format:
Attribution is baked into payload.data — the full calldata is already {ABI-encoded call}{attribution suffix}. The wallet receives a single opaque hex string and sends it as-is. Attribution cannot be lost regardless of what wallet or provider you use.
for (const step of steps) { // payload.data = ABI calldata + attribution suffix, pre-concatenated await walletClient.sendTransaction(step.payload)}
Best for: backend scripts, server-side signing, embedded wallets (Privy, Dynamic, passkey signers), any flow that uses eth_sendRawTransaction directly, or anywhere you want eth_call pre-simulation on the exact calldata that will be broadcast.
Attribution is in step.tx.attribution as standalone bytes. You must pass it as dataSuffix to writeContract — wagmi appends it to the ABI-encoded calldata before sending. If dataSuffix is omitted or the EIP-1193 provider strips it, the transaction succeeds on-chain but volume is not attributed.
for (const step of steps) { await walletClient.writeContract({ address: step.tx.address, abi: step.tx.abi, functionName: step.tx.functionName, args: step.tx.args, account: step.tx.account, dataSuffix: step.tx.attribution, // ← required for attribution; omitting silently drops it })}
Best for: browser wallets via wagmi (MetaMask, Coinbase Wallet, WalletConnect), or when you need wagmi’s type-safe simulation hooks (simulateContract).Note: Most major EIP-1193 providers used with wagmi honor dataSuffix. If you’re using a custom or obscure provider, verify it forwards unknown WriteContractParameters fields before relying on this path for attribution.
Use the vault’s chain_id:address string (e.g. gtBTC on Ethereum is 1:0xeff0ae5b39271b33f448cd408b51dc8aa72a672b) to filter events by vault: GET /v1/events?vault_id=1:0xeff0ae5b39271b33f448cd408b51dc8aa72a672b.Use transactions for user-facing activity and confirmations. Use events for monitoring, reconciliation, and reporting.