Learn how OneBalance automatically handles token approvals for DeFi operations while maintaining security best practices.
Important : Never manually call approve()
functions when using OneBalance. The platform automatically manages all required approvals as part of the contract call preparation process.
How Approval Management Works
When you specify allowanceRequirements
, OneBalance automatically:
Checks existing allowances - Verifies current approval amounts
Adds approval transactions - Only when needed, for exact amounts
Executes your operations - Runs your contract calls
Removes excess approvals - Cleans up remaining allowances for security
This prevents front-running attacks and ensures optimal gas usage.
OneBalance bundles approvals, your calls, and approval cleanup into a single user operation for atomic execution.
Basic Example
Here’s how to properly handle approvals for a DEX swap:
import { encodeFunctionData , parseAbi , parseUnits } from 'viem' ;
const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' ;
const UNISWAP_ROUTER = '0x2626664c2603336E57B271c5C0b26F421741e481' ;
// ✅ Correct - Let OneBalance handle approvals
const prepareRequest = {
account: {
sessionAddress: '0x...' ,
adminAddress: '0x...' ,
accountAddress: '0x...'
},
targetChain: 'eip155:8453' , // Base
calls: [{
to: UNISWAP_ROUTER ,
data: encodeFunctionData ({
abi: parseAbi ([ 'function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96))' ]),
functionName: 'exactInputSingle' ,
args: [{
tokenIn: USDC_BASE ,
tokenOut: '0x...' ,
fee: 3000 ,
recipient: account . accountAddress ,
deadline: Math . floor ( Date . now () / 1000 ) + 3600 ,
amountIn: parseUnits ( '100' , 6 ), // 100 USDC
amountOutMinimum: 0 ,
sqrtPriceLimitX96: 0
}]
}),
value: '0'
}],
allowanceRequirements: [{
assetType: `eip155:8453/erc20: ${ USDC_BASE } ` ,
amount: parseUnits ( '100' , 6 ). toString (), // Exact amount needed
spender: UNISWAP_ROUTER
}],
tokensRequired: [{
assetType: `eip155:8453/erc20: ${ USDC_BASE } ` ,
amount: parseUnits ( '100' , 6 ). toString ()
}]
};
What NOT to Do
Common Mistake : Including approval calls manually will cause transaction failures.
// ❌ WRONG - Don't do this!
const badRequest = {
calls: [
{
// This will cause the transaction to fail
to: USDC_BASE ,
data: encodeFunctionData ({
abi: parseAbi ([ 'function approve(address spender, uint256 amount)' ]),
functionName: 'approve' ,
args: [ UNISWAP_ROUTER , parseUnits ( '100' , 6 )]
}),
value: '0'
},
{
to: UNISWAP_ROUTER ,
data: swapCallData ,
value: '0'
}
]
// No allowanceRequirements - this is the problem!
};
Common Patterns
DEX Swaps
// Uniswap V3 swap requiring token approval
allowanceRequirements : [{
assetType: `eip155:8453/erc20: ${ inputToken } ` ,
amount: inputAmount . toString (),
spender: UNISWAP_V3_ROUTER
}]
Lending Protocols
// Aave deposit requiring pool approval
allowanceRequirements : [{
assetType: `eip155:1/erc20: ${ asset } ` ,
amount: depositAmount . toString (),
spender: AAVE_POOL_ADDRESS
}]
Multiple Token Operations
// Complex DeFi operation requiring multiple approvals
allowanceRequirements : [
{
assetType: `eip155:1/erc20: ${ tokenA } ` ,
amount: amountA . toString (),
spender: DEX_ROUTER
},
{
assetType: `eip155:1/erc20: ${ tokenB } ` ,
amount: amountB . toString (),
spender: LENDING_POOL
}
]
NFT Purchases
// NFT marketplace purchase with USDC
allowanceRequirements : [{
assetType: 'eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ,
amount: nftPrice . toString (),
spender: NFT_MARKETPLACE_ADDRESS
}]
Special Cases
Native Tokens (ETH, MATIC, etc.)
Native tokens don’t require approvals - they’re sent directly:
// No allowanceRequirements needed for ETH
calls : [{
to: CONTRACT_ADDRESS ,
data: contractCallData ,
value: ethAmount . toString () // Send ETH directly
}],
tokensRequired : [{
assetType: 'eip155:1/slip44:60' , // ETH
amount: ethAmount . toString ()
}]
// No allowanceRequirements array needed
Existing Allowances
OneBalance optimizes gas by checking existing allowances:
Sufficient Allowance If current allowance ≥ required amount
, no approval transaction is added
Insufficient Allowance Only approves the exact amount needed, not unlimited approvals
Security Features
OneBalance’s approval management includes several security measures:
Exact Amount Approvals - Never approves more than needed
Automatic Cleanup - Removes remaining allowances after execution
Front-running Protection - Atomic bundling prevents manipulation
Approval Validation - Verifies spender addresses match your calls
Best Practices
Use allowanceRequirements
Always specify token approvals in the allowanceRequirements
array, never in calls
Specify Exact Amounts
Use precise amounts to minimize approval exposure
Verify Spender Addresses
Double-check that spender addresses match your contract calls
Test with Small Amounts
Start with small transactions to verify your integration
TypeScript Interface
interface AllowanceRequirement {
assetType : string ; // Format: "eip155:chainId/erc20:tokenAddress"
amount : string ; // Amount in smallest unit (e.g., wei)
spender : string ; // Contract address that needs approval
}
interface PrepareCallRequest {
account : Account ;
targetChain : string ;
calls : CallData [];
allowanceRequirements : AllowanceRequirement [];
tokensRequired : TokenRequirement [];
}
Troubleshooting
Transaction fails with ‘Approval not found’ - Make sure you’re using allowanceRequirements
instead of manual approval calls.
Gas costs seem high - OneBalance only adds approvals when needed. High gas might indicate multiple tokens or complex operations.
Spender address mismatch - Verify that the spender in allowanceRequirements
matches the contract address in your calls
.
Amount calculation errors - Ensure you’re using the correct decimals for the token (e.g., 6 for USDC, 18 for most ERC20s).
Responses are generated using AI and may contain mistakes.