Token Management
Manage which tokens count as collateral and revoke unnecessary token allowances on your credit account.
Enabling and Disabling Tokens
Why
You manually enable/disable tokens when:
- Direct transfers - Tokens sent directly to a Credit Account aren't auto-enabled
- Gas optimization - Disable unused tokens to reduce collateral check cost
- Risk management - Prevent certain tokens from counting in health factor
Most of the time you don't need this - tokens auto-enable/disable based on balance changes from adapter calls. Manual control is only necessary in edge cases.
Auto-Enable/Disable Behavior
Non-quoted tokens have automatic behavior:
| Balance Change | Action |
|---|---|
| 0/1 to > 1 | Auto-enable |
| > 1 to 0/1 | Auto-disable |
Important: These functions only work on non-quoted tokens. Quota tokens can only be enabled/disabled via updateQuota.
Enable a Token
import { encodeFunctionData } from 'viem'; import { iCreditFacadeV300MulticallAbi } from '@gearbox-protocol/sdk'; const calls = [ { target: creditFacadeAddress, callData: encodeFunctionData({ abi: iCreditFacadeV300MulticallAbi, functionName: 'enableToken', args: [tokenAddress], }), }, ];
Disable a Token
const calls = [ { target: creditFacadeAddress, callData: encodeFunctionData({ abi: iCreditFacadeV300MulticallAbi, functionName: 'disableToken', args: [tokenAddress], }), }, ];
Disable Unused Tokens to Save Gas
Each enabled token requires a price oracle call during collateral check. Disable tokens with zero balance:
// Check which tokens have zero balance const accountData = await service.getCreditAccountData(creditAccountAddress); const tokensToDisable = accountData.tokens .filter(t => t.balance <= 1n && t.isEnabled) .map(t => t.token); const calls = tokensToDisable.map(token => ({ target: creditFacadeAddress, callData: encodeFunctionData({ abi: iCreditFacadeV300MulticallAbi, functionName: 'disableToken', args: [token], }), }));
Enable/Disable Gotchas
- No-op for quota tokens - Calling
enableTokenordisableTokenon a quota token does nothing. UseupdateQuotainstead. - Cannot enable forbidden tokens - Forbidden tokens will revert. They must be swapped away.
- Max enabled tokens limit - Each Credit Manager has a maximum number of enabled tokens per account. Check with
creditManager.read.maxEnabledTokens(). - Disabled tokens still on account - Disabling doesn't remove the balance, it just excludes the token from the health factor calculation. During liquidation, liquidators can claim disabled token balances as bonus.
- Balance of 1 is "zero" - Gearbox treats balances of 0 and 1 the same (due to ERC20 rounding). Auto-disable triggers at balance <= 1.
Revoking Allowances
Why
You revoke allowances when:
- Security incident - A third-party contract may be compromised
- Legacy cleanup - Old accounts from V2.1 may have stale approvals
- Defense in depth - Proactively remove unnecessary approvals
Current Gearbox V3 automatically resets allowances to 1 after each interaction, so this is mainly needed for legacy accounts or incident response.
How It Works
revokeAdapterAllowances resets token approvals from your Credit Account to specified contracts. Allowance is set to 1 (not 0) due to gas optimization.
Basic Usage
import { encodeFunctionData } from 'viem'; import { iCreditFacadeV300MulticallAbi } from '@gearbox-protocol/sdk'; // Define which approvals to revoke const revocations = [ { spender: uniswapRouterAddress, token: usdcAddress, }, { spender: curvePoolAddress, token: daiAddress, }, ]; const calls = [ { target: creditFacadeAddress, callData: encodeFunctionData({ abi: iCreditFacadeV300MulticallAbi, functionName: 'revokeAdapterAllowances', args: [revocations], }), }, ]; await market.creditFacade.write.multicall([creditAccountAddress, calls]);
Check Existing Allowances
import { erc20Abi, getContract } from 'viem'; const token = getContract({ address: tokenAddress, abi: erc20Abi, client: publicClient, }); // Check allowance from Credit Account to a spender const allowance = await token.read.allowance([ creditAccountAddress, spenderAddress, ]); if (allowance > 1n) { console.log(`Credit Account has ${allowance} allowance to ${spenderAddress}`); }
Revoke All Known Adapters
// Get all adapters from Credit Manager const adapters = await creditManager.read.adapters(); // Build revocations for all adapters const revocations = adapters.map(adapter => ({ spender: adapter, token: tokenAddress, })); const calls = [ { target: creditFacadeAddress, callData: encodeFunctionData({ abi: iCreditFacadeV300MulticallAbi, functionName: 'revokeAdapterAllowances', args: [revocations], }), }, ];
Revocation Gotchas
- Usually not needed in V3 - Gearbox V3 automatically resets allowances after each adapter interaction.
- Sets to 1, not 0 - For gas efficiency, allowances are set to 1 instead of 0. An allowance of 1 wei is functionally zero.
- Target the adapter, not the protocol - Revocations target the spender (adapter address), not the underlying protocol.
- Batch multiple revocations - Pass multiple
(spender, token)pairs in a singlerevokeAdapterAllowancescall for efficiency.
When to Actually Revoke
Real scenarios where revocation makes sense:
- Third-party exploit - A protocol Gearbox integrates with gets hacked
- Account migration - Moving from V2.1 account with old allowances
- Compliance requirement - Regulatory frameworks requiring revoked unused approvals
- Personal security policy - Explicit control over all approvals
Learn More
- External Calls - How adapters use allowances
- Updating Quotas - How to enable/disable quota tokens
- Slippage & Safety - Related safety controls