In many scenarios, you might want to know how much X of TokenA you'll receive for Y of TokenB. Fortunately, Balancer has query functions to simulate transactions.
{% hint style="warning" %}
If you look on Etherscan (or similar), all three of the query functions will show up as "Write" functions. That is ok! You can still call these with eth_call
to get numerical results without spending any gas.
{% endhint %}
If you are using queryBatchSwap
, queryJoin
, or queryExit
to calculate limits
, maxAmountsIn
, or minAmountsOut
, this is ONLY useful if you simulate these calls OUTSIDE of the transaction you end up making. You SHOULD NOT call these functions to calculate limits from a smart contract at transaction time.
There are valid use cases for calling these functions on chain, but do not use them to determine limits.
Calculating these values ahead of time is useful for enforcing slippage tolerances to mitigate losses due to sandwich attacks. If you are querying these values at execution time, you end up getting your values mid-sandwich! This leaves you entirely vulnerable to the attacker's manipulation, and is as foolish as using a 100% slippage tolerance.
{% hint style="info" %}
*LinearPools and StablePhantomPools do not have join or exit functionality since those are handled as swaps! For example, if you want to figure out how much bb-a-USD
you'll get for an amount of DAI
, you'll need to use queryBatchSwap
on a trade route that swaps DAI
for bb-a-DAI
and then swaps bb-a-DAI
for bb-a-USD
.
{% endhint %}
To calculate the inputs/outputs for a trade (you can specify given-in or given-out), you will use the queryBatchSwap
function in the Vault
. This functionality is important if not crucial for calculating your limits when constructing your batchSwap
arguments.
queryBatchSwap(
SwapKind kind,
BatchSwapStep[] swaps,
IAsset[] assets,
FundManagement funds)
returns (int256[] assetDeltas)
To calculate amounts of BPT out and tokens in, you will use queryJoin
in BalancerHelpers
. This functionality is important for calculating maxAmountsIn
and/or minBptOut
on joins
queryJoin(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest request)
returns (uint256 bptOut, uint256[] amountsIn)
To calculate amounts of BPT in and tokens out, you will use queryExit
in BalancerHelpers
. This functionality is important for calculating minAmountsOut
and/or maxBptIn
on exits.
queryExit(
bytes32 poolId,
address sender,
address recipient,
ExitPoolRequest request)
returns (uint256 bptIn, uint256[] amountsOut)
The query function perform no checks on the sender
and recipient
field in the fund structs. This makes it suitable to be called by off-chain applications via eth_call
without needing to hold tokens, approve them for the Vault, or even know a user's address. Similarly for joins
and exits
, these go directly to the pool and bypass the vault (which does the checks).