Check Eligibility
Every check on this page is a free contract read. Run them before submitting a swap.
Prerequisites
- Authorizations are in place — see Setup
- You have the pool address, the token addresses, and an RPC endpoint
- You know your calling contract's address
Step 1: Set up a read client
import { createPublicClient, http, parseAbi } from 'viem';
const client = createPublicClient({ transport: http(process.env.RPC_URL) });
const POOL = '0xYOUR_POOL_ADDRESS';
const IBENJI = '0xIBENJI_TOKEN_ADDRESS';
const USDC = '0xUSDC_TOKEN_ADDRESS';
const CALLER = '0xYOUR_CALLING_CONTRACT_ADDRESS';
const poolAbi = parseAbi([
'function isTraderAllowed(address trader, address tokenA, address tokenB) view returns (bool)',
'function isTokenPairAuthorized(address tokenA, address tokenB) view returns (bool)',
'function paused() view returns (bool)',
'function getTokenBalance(address token) view returns (uint256)',
'function registeredTokens(address token) view returns (bool isRegistered, uint8 decimals)'
]);
const erc20Abi = parseAbi([
'function balanceOf(address owner) view returns (uint256)',
'function allowance(address owner, address spender) view returns (uint256)'
]);
Step 2: Are you allowed to trade this pair?
const allowed = await client.readContract({
address: POOL, abi: poolAbi, functionName: 'isTraderAllowed',
args: [CALLER, USDC, IBENJI]
});
true means you can trade this pair. If it returns false, your authorization is not in place yet — contact Franklin Templeton to complete it before going further. See Setup.
The trader address comes first. isTraderAllowed(trader, tokenA, tokenB) — passing the arguments in another order silently looks up a token as the trader and returns false for everything.
Use the same call to check a third-party destination. A destination is accepted when it is authorized on the pair, so if you intend to deliver output to an address other than your calling contract, read that address the same way:
const destinationOk = await client.readContract({
address: POOL, abi: poolAbi, functionName: 'isTraderAllowed',
args: [DESTINATION, USDC, IBENJI]
});
false means the destination is not authorized yet and the swap would be refused — ask Franklin
Templeton to authorize it, the same request as for your own contract. Note this is necessary but not
sufficient: your contract must also grant its own
per-destination approval, which is a separate record.
Step 3: Is the pair supported, and is the pool accepting swaps?
const [pairOk, isPaused] = await Promise.all([
client.readContract({
address: POOL, abi: poolAbi,
functionName: 'isTokenPairAuthorized', args: [USDC, IBENJI]
}),
client.readContract({ address: POOL, abi: poolAbi, functionName: 'paused' })
]);
paused() is the correct way to check whether the pool is accepting swaps. A successful preview does not tell you this.
Step 4: Do you hold enough, and have you approved the pool?
const [balance, allowance] = await Promise.all([
client.readContract({
address: USDC, abi: erc20Abi,
functionName: 'balanceOf', args: [CALLER]
}),
client.readContract({
address: USDC, abi: erc20Abi,
functionName: 'allowance', args: [CALLER, POOL]
})
]);
Check the balance of the calling contract. The pool debits the caller, not the signing wallet and not the destination.
Step 5: Can the pool fill your size?
const reserve = await client.readContract({
address: POOL, abi: poolAbi, functionName: 'getTokenBalance', args: [IBENJI]
});
Use getTokenBalance(token), not balanceOf(pool). The reserve is not necessarily held at the
pool's own address, so balanceOf on the pool can return a figure unrelated to what it is able to
deliver — in either direction, and sometimes zero while the reserve is substantial. getTokenBalance
is the deliverable figure, so treat that as the one to plan against.
Swaps are all-or-nothing. If your amount exceeds the reserve, the swap reverts with refused and delivers nothing — it does not partially fill. Reduce the amount and try again.
The revert will not tell you the maximum. Error messages carry no numbers, so if a swap fails on size, re-read getTokenBalance and recompute rather than guessing. Reserves also move as other participants swap, so read this immediately before you submit.
A preview will not catch this. quoteNet returns a quote for any amount you ask about, including one far larger than the pool's whole reserve — so a successful quote is not evidence the pool can fill you. This read is the check; the quote is only the price.
Step 6: What fee applies to you?
Read the fee rather than hard-coding it — it can vary, and it can change. Get the figure for the exact swap you are about to make from Preview a swap, requesting it as your contract's address. See Your contract is the trader.
Step 7: What decimals apply, and is there a minimum?
Both come from the pool, and both change what amount you are allowed to send.
Read decimals from the pool, not from the token contract. registeredTokens returns the values the
pool cached when the token was registered, and those are the values it uses for every conversion.
const [, iBenjiDecimals] = await client.readContract({
address: POOL, abi: poolAbi, functionName: 'registeredTokens', args: [IBENJI]
});
A pair can carry a minimum input amount, and a single direction can carry its own that overrides it. Check both, so a minimum is something you read rather than something a refusal tells you. The two hashes are computed differently: the pair hash comes from the pool and is order-independent, the direction hash you compute yourself and the order matters.
See Pool interface for both reads and the worked example.
A minimum of 0 means none is set.
Reading all of this at once
The reads above are deliberately independent, so they work no matter how your contract is built. If you would rather bundle them, your own contract can expose a single view that performs them together — worth doing for one reason in particular: separate reads can land at different chain heights and disagree with each other, while one call gives you a consistent view.
Save these outputs
Before moving on, you should have confirmed:
- you are allowed to trade the pair
- any third-party destination is authorized on that pair too
- the pair is supported and the pool is not paused
- the calling contract holds enough, and the pool has an allowance
- the pool reserve covers your amount
- the fee for your swap, quoted as your contract's address
- both tokens' decimals, read from the pool, and any minimum that applies to your amount