Swap
Swapping on BarkSwap is a two-step flow: quote the expected output with QuoterV2, then
execute the trade through SwapRouter. This page uses exactInputSingle (a single-hop,
exact-input swap). Examples use ethers v6 — the version used by the
BarkSwap frontend.
BarkSwap's exactInputSingle takes a deployer field instead of Uniswap v3's fee. Pass
address(0) (0x0000…0000) to target the default pool deployer. There is no fee tier — the pool's
fee is dynamic.
1. Approve the input token
SwapRouter pulls tokenIn via transferFrom, so approve it first (skip this for native-DOGE
swaps, which wrap automatically when you send value).
import { Contract, MaxUint256 } from 'ethers';
const ERC20_ABI = ['function approve(address spender, uint256 amount) returns (bool)'];
const SWAP_ROUTER = '0x911E5A1630fD1768E5A1710DAAFaBb865cB79531';
const token = new Contract(tokenIn, ERC20_ABI, signer);
await (await token.approve(SWAP_ROUTER, MaxUint256)).wait();
2. Quote the output
import { Contract } from 'ethers';
const QUOTER_V2 = '0x187b41968063Cb8A04A5f4d2113844EF2Ba21493';
const ZERO = '0x0000000000000000000000000000000000000000';
const QUOTER_ABI = [
'function quoteExactInputSingle((address tokenIn,address tokenOut,address deployer,uint256 amountIn,uint160 limitSqrtPrice)) returns (uint256 amountOut, uint16 fee, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)',
];
const quoter = new Contract(QUOTER_V2, QUOTER_ABI, provider);
// QuoterV2 is non-view internally; use staticCall to read the return values.
const [amountOut] = await quoter.quoteExactInputSingle.staticCall({
tokenIn,
tokenOut,
deployer: ZERO,
amountIn,
limitSqrtPrice: 0n,
});
3. Execute the swap
Apply your slippage tolerance to the quote to get amountOutMinimum.
const SWAP_ROUTER = '0x911E5A1630fD1768E5A1710DAAFaBb865cB79531';
const ROUTER_ABI = [
'function exactInputSingle((address tokenIn,address tokenOut,address deployer,address recipient,uint256 deadline,uint256 amountIn,uint256 amountOutMinimum,uint160 limitSqrtPrice)) payable returns (uint256 amountOut)',
];
const router = new Contract(SWAP_ROUTER, ROUTER_ABI, signer);
const slippageBps = 50n; // 0.5%
const amountOutMinimum = (amountOut * (10_000n - slippageBps)) / 10_000n;
const tx = await router.exactInputSingle({
tokenIn,
tokenOut,
deployer: ZERO,
recipient: await signer.getAddress(),
deadline: Math.floor(Date.now() / 1000) + 60 * 10,
amountIn,
amountOutMinimum,
limitSqrtPrice: 0n,
});
await tx.wait();
Multi-hop swaps
For routes that cross more than one pool, use exactInput with an encoded path. The BarkSwap path
is tokenA · tokenB · tokenC packed addresses (20 bytes each, no fee bytes between them, unlike
Uniswap v3):
import { solidityPacked } from 'ethers';
const path = solidityPacked(['address', 'address', 'address'], [tokenA, tokenB, tokenC]);
Gotchas
- Approve before swapping.
SwapRoutercannot move your tokens otherwise. deployer, notfee. Useaddress(0)for default pools — there are no fixed tiers.QuoterV2reverts to return data. Read it with.staticCall(ethers v6) /callStatic.- Deadlines. A too-tight
deadlinereverts under congestion; 5–10 minutes is typical. - Native DOGE. Send
valueand use the WDOGE address for the wrapped leg; the router handles (un)wrapping when configured with a multicall +unwrapWNativeToken.