Skip to main content

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.

Parameter shape

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. SwapRouter cannot move your tokens otherwise.
  • deployer, not fee. Use address(0) for default pools — there are no fixed tiers.
  • QuoterV2 reverts to return data. Read it with .staticCall (ethers v6) / callStatic.
  • Deadlines. A too-tight deadline reverts under congestion; 5–10 minutes is typical.
  • Native DOGE. Send value and use the WDOGE address for the wrapped leg; the router handles (un)wrapping when configured with a multicall + unwrapWNativeToken.