Skip to main content
Everything you need for production swaps.

Best practices

Token decimals

The program supports tokens with different decimal precision. Amounts are automatically normalized during swaps so equivalent values are preserved across different decimal precisions.
EVM tokens commonly use 6 decimals (USDC) or 18 decimals. The contract normalizes between them automatically.
// Example: expressing 100 tokens for a 6-decimal token (e.g., USDC)
const amount = ethers.parseUnits("100", 6);

// Example: expressing 100 tokens for an 18-decimal token
const amount18 = ethers.parseUnits("100", 18);
You can query a token’s decimals from the contract:
const decimals = await stableSwapper.getTokenDecimals(tokenAddress);

Slippage protection

Always set minAmountOut to protect against fee rate changes between when you construct the transaction and when it executes.
// Read fee from contract and calculate expected output
const feeBps = await stableSwapper.feeBasisPoints();
const amountIn = ethers.parseUnits("100", 6);

// Fee is charged on the input token, rounded up
const fee = (amountIn * BigInt(feeBps) + 9999n) / 10000n;
const expectedOutput = amountIn - fee;

// Apply slippage tolerance (2%)
const slippageBps = 200n;
const minAmountOut = expectedOutput * (10000n - slippageBps) / 10000n;

Allowlist

The allowlist may be enabled for this pool. When active, only allowlisted addresses can execute swaps. Transactions from non-allowlisted addresses will fail. Contact your integration partner to be added to the allowlist.
For smart contract integrations: The calling contract’s address (msg.sender) must be allowlisted, not the EOA that initiated the outer transaction. You can check allowlist status before sending a transaction:
const allowlistEnabled = await stableSwapper.isFeatureEnabled(2); // 2 = ALLOWLIST
if (allowlistEnabled) {
  const isAllowed = await stableSwapper.isAllowlisted(walletAddress);
  if (!isAllowed) {
    throw new Error("Address not allowlisted");
  }
}

ERC-20 approvals (Base only)

Before swapping on Base, the Stableswapper contract must be approved to transfer your input tokens. This is a standard ERC-20 requirement.
const token = new ethers.Contract(tokenInAddress, ERC20_ABI, signer);

// Option 1: Approve exact amount (most secure, requires approval per swap)
await token.approve(STABLESWAPPER_ADDRESS, amountIn);

// Option 2: Approve a larger amount to avoid repeated approvals
await token.approve(STABLESWAPPER_ADDRESS, ethers.MaxUint256);
Approving MaxUint256 is convenient but gives the contract unlimited spending authority over that token. For production, consider approving exact amounts or using a reasonable upper bound.

Security considerations

  1. Verify the contract address before sending transactions — use the address from the Key Addresses page
  2. Double-check token addresses — confirm both input and output token addresses against the Key Addresses page
  3. Validate user inputs — sanitize and bounds-check all amounts and addresses
  1. Test on devnet/testnet first with small amounts
  2. Run integration tests covering success and failure cases
  3. Test edge cases like zero amounts, maximum amounts, and missing accounts or approvals
  1. Never assume success — always check transaction results
  2. Provide clear error messages to users
  3. Implement retry logic for network failures (but not for validation errors)
  1. Log transaction signatures/hashes for debugging and support
  2. Track failed transactions to identify patterns
  3. Monitor pool liquidity to warn users before failures

Pre-flight checklist

Before sending a swap on mainnet, verify:
  • User has sufficient input token balance
  • User has sufficient ETH for gas fees
  • ERC-20 approval is set for the Stableswapper contract on the input token
  • Both tokens are listed and swappable
  • Swap feature is enabled
  • Contract has sufficient output token liquidity (balance minus reserved amount)
  • User address is allowlisted (if allowlist feature is enabled)
  • Slippage tolerance accounts for current fee rate
  • Contract address and token addresses match the Key Addresses page
See Key Addresses for all contract and token addresses.

Troubleshooting

Common errors and solutions

Examples

Code samples for common scenarios

Reference

Swap instruction parameters

Quickstart

Get up and running in 10 minutes